我正在尝试为无向加权图创建一个邻接列表,这样我就可以运行Dijkstra和Kruskal的算法了,我遇到了一个有趣的问题。每当我尝试向列表索引添加第二个边缘时,似乎它在函数调用期间将列表索引更改为新边缘,从而擦除上一个边缘列表索引指向的内容。 (我认为这个人有类似的问题,但没有答案:How to create an adjacency list of a directed graph in C?)。这是代码:
#include <stdio.h>
#include <stdlib.h>
// Edge node
struct edge{
int v1; // vertex it's coming from
int v2; // vertex it's going to
int weight; // weight of edge
struct edge *next;
}
const int MAX = 9;
void createAdjList(struct edge **list);
struct createEdge(int v1, int v2, int weight);
void addEdge(struct edge **list, struct edge newEdge);
int main(){
struct edge *list = malloc(MAX * sizeof(struct edge));
createAdjList(&list);
...
return 0;
}
// creates the adjacency list
void createAdjList(struct edge **list){
for(int i = 0; i < MAX; ++i)
list[i] = 0;
// first edge from vertex 0 to 1
addEdge(list, createEdge(0, 1, 22));
addEdge(list, createEdge(1, 0, 22));
// this is where the problem happens, when i call addEdge(list, createEdge(0, 2, 9));
// as soon as it enters addEdge, list[0] goes from pointing to the 0-1 edge to already
// pointing to this second edge, 0 to 2
// second edge from vertex 0 to 2
addEdge(list, createEdge(0, 2, 9));
addEdge(list, createEdge(2, 0, 9));
...
}
// creates and returns an edge node
struct createEdge(int v1, int v2, int weight){
struct edge newEdge;
newEdge.v1 = v1;
newEdge.v2 = v2;
newEdge.weight = weight;
newEdge.next = 0;
return newEdge;
}
// adds the edge to the adjacency list
void addEdge(struct edge **list, struct edge newEdge){
// at this point, after the addEdge(list, createEdge(0, 2, 9)); call, list[0] is now
// pointing to this new edge and Edge(0, 1, 22) is gone
for(int i = 0; i < MAX; ++i){
// if edge vertex equals index i
if(newEdge.v1 == i){
// if list index is empty, place it at head and return
if(list[i] == 0){
list[i] = &newEdge;
return;
// else traverse to the end, place it and return
}else{
struct edge* curr = list[i];
while(curr->next != 0)
curr = curr->next;
curr->next = &newEdge;
return;
}
}
}
}
感谢
答案 0 :(得分:0)
list[i] = &newEdge;
这里newEdge
是一个函数参数,它与局部变量相同,因为它在函数addEdge
返回时被销毁。
因此,在addEdge
返回后,列表中有一个指针指向newEdge
曾经的位置。有可能边缘的值仍然存在,并且可能在下次调用函数时内存将被重用于其他内容。在你的情况下,碰巧被重用来保持下一个边缘。
解决方案是malloc
一些空格来保持列表中的边缘。分配有malloc
的内存无法重复使用,直到free
为止。