【问题标题】:Problems initializing a Graph based on Array with adjacency lists in C基于 C 中具有邻接列表的数组初始化图的问题
【发布时间】:2011-02-04 23:48:51
【问题描述】:

我以前玩过 Graphs,在 StackOverflow 的帮助下我管理得很好,但我从未使用过像下面这样的结构。我似乎无法理解我在这里做错了什么......

#include "stdio.h"
#include "stdlib.h"

#define MaxV 100
#define MaxE 50

typedef struct edge {
    int dest;
    int cost;

    struct edge *next;
} Edge, *Graph[MaxV];

Graph *initGraph() {    
    Graph *g = (Graph*)malloc(sizeof(Edge) * MaxV);

    for(int i = 0; i < MaxV; i++)
        (*g[i])->next = NULL;

    return g;
}

int main(void) {
    Graph *g = initGraph();

    for(int i = 0; i < MaxV; i++) {
        if((*g[i])->next == NULL) printf("[%02d] NULL\n", i);
    }

    return 0;
}

我在(*g[i])-&gt;next = NULL; 的第一次迭代中遇到了分段错误,我不明白为什么。我已经尝试了无数的事情,但我似乎无法用这种结构管理 Graph 初始化。另外,我声明和返回指向 Graph 的指针的方式是否适合这个结构?

我是在 init 函数中使用大量指针使事情复杂化还是什么?

P.S:请不要提出不同的结构定义,我无法更改上述结构中的任何内容。这才是真正的问题。我知道如何使用 Graphs 滚动我自己的结构,但我需要使用上面的那个。

【问题讨论】:

  • 您是否尝试过使用调试器?我不确定g 是如何分配的。
  • 是的,这就是我意识到它在第一次迭代时中断的原因,因为我虽然后来中断了,可能是因为我没有分配足够的内存。但是我发现 GDB 很混乱,我不知道如何正确使用它。

标签: c pointers graph initialization structure


【解决方案1】:

我不太明白你的第二个 typedef *Graph[MaxV]

我要做的是声明另一个结构如下:

typedef struct graph {
    Edge *edges;
} Graph;

然后可以如下初始化图:

Graph *initGraph() {  
    Graph *g = (Graph*)malloc(sizeof(Graph));

    g->edges = (Edge*)malloc(sizeof(Edge) * MaxV);
    for(int i = 0; i < MaxV; i++)
        g->edges[i].next = NULL;

    return g;
}

打印出来的图形如下:

for(int i = 0; i < MaxV; i++) {
    if(g->edges[i].next == NULL) printf("[%02d] NULL\n", i);
}

我想你会发现,随着时间的推移,为图表添加一个额外的结构也将被证明更具可持续性。 :)

【讨论】:

  • 我无法更改结构定义。这是真正的问题,我知道没有这样的结构怎么做,但我特别需要这个。
【解决方案2】:

鉴于 OP 要求不以任何方式更改 typedef,完整修订答案。

我建议改成这个:

void initGraph(Graph g) {
    g[0] = malloc(sizeof(Edge) * MaxV);

    for(int i = 0; i < MaxV; i++)
        g[0][i].next = NULL;
    return;
}

int main(void) {
    Graph g;
    initGraph(g);

    for(int i = 0; i < MaxV; i++) {
        if(g[0][i].next == NULL) printf("[%02d] NULL\n", i);
    }

    free(g[0]);
    return 0;
}

这里的问题是“指针数组”综合症。即Graph** g 等价于Graph *g[10],明显的附带条件是外部数组大小是固定的。这会产生问题,因为您 can't return a fixed size array,但您可以返回 **

我仍然不确定图形数组的用例是什么,但见鬼,这通过了 valgrind。

【讨论】:

  • 我不能改,我需要这样用。
  • 好的,我已经修好了。我花了一些时间才弄清楚它,这里已经很晚了。
  • 感谢您的解决方案,但必须有另一种方法,没有g[0],这似乎很奇怪。如果真的是你说的Graph** g,为什么我们不能直接返回指向第一个元素的指针呢?
【解决方案3】:

我想我找到了我正在寻找的解决方案。我尽可能地使用 Valgrind 来测试读/写权限,并且没有错误。是的,存在内存泄漏,但这不是这个问题的重点(我知道这些,别担心)。

这是创建简单图表的完整代码。很想听听这个实现可能遇到的任何问题......

#include "stdio.h"
#include "stdlib.h"

#define MaxV 10
#define MaxE 5

typedef struct edge {
    int dest;
    int cost;

    struct edge *next;
} Edge, *Graph[MaxV];

Graph *initGraph() {
    Graph *g = (Graph*)malloc(sizeof(Graph));

    for(int i = 0; i < MaxV; i++)
        (*g)[i] = NULL;

    return g;
}

int insertEdge(Graph *g, int o, int d, int c) {
    if(!g) return -1;

    Edge *edge = (Edge*)malloc(sizeof(Edge));

    edge->dest = d;
    edge->cost = c;

    edge->next = (*g)[o];
    (*g)[o] = edge;

    return 0;
}

int main(void) {
    Graph *g1 = initGraph();
    Edge *aux = NULL;

    insertEdge(g1, 0, 1, 2);
    insertEdge(g1, 0, 2, 3);
    insertEdge(g1, 1, 4, 5);
    insertEdge(g1, 2, 4, 1);
    insertEdge(g1, 4, 8, 6);

    for(int i = 0; i < MaxV; i++) {
        printf("[%02d]\n", i);

        for(aux = (*g1)[i]; aux != NULL; aux = aux->next)
            printf(" [%d] » [%d] (%d)\n", i, aux->dest, aux->cost);
    }

    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-01
    • 1970-01-01
    • 2023-03-13
    • 2011-01-14
    • 2020-08-08
    • 1970-01-01
    • 2010-12-22
    相关资源
    最近更新 更多