C语言中邻接表图的实现

C语言中邻接表图的实现,c,graph,adjacency-list,C,Graph,Adjacency List,我读了一段代码,它实现了一个带有邻接列表的图。但是我对加法函数非常困惑 在下面代码的函数中,当使用数组[src].head为newNode->next赋值时。这意味着newNode的下一个节点是数组[src].head。但是在语句“graph->array[src].head=newNode;”之后,当我们测试结果时,顺序正好相反。有人能给我解释一下吗?谢谢 #include <stdio.h> #include <stdlib.h> // A structure

我读了一段代码,它实现了一个带有邻接列表的图。但是我对加法函数非常困惑

在下面代码的函数中,当使用数组[src].head为newNode->next赋值时。这意味着newNode的下一个节点是
数组[src].head。但是在语句“graph->array[src].head=newNode;”之后,当我们测试结果时,顺序正好相反。有人能给我解释一下吗?谢谢

#include <stdio.h> 
#include <stdlib.h> 

// A structure to represent an adjacency list node 
struct AdjListNode 
{ 
    int dest; 
    struct AdjListNode* next; 
}; 

// A structure to represent an adjacency list 
struct AdjList 
{ 
    struct AdjListNode *head;  
}; 

// A structure to represent a graph. A graph 
// is an array of adjacency lists. 
// Size of array will be V (number of vertices  
// in graph) 
struct Graph 
{ 
    int V; 
    struct AdjList* array; 
}; 

// A utility function to create a new adjacency list node 
struct AdjListNode* newAdjListNode(int dest) 
{ 
    struct AdjListNode* newNode = 
     (struct AdjListNode*) malloc(sizeof(struct AdjListNode)); 
    newNode->dest = dest; 
    newNode->next = NULL; 
    return newNode; 
} 

// A utility function that creates a graph of V vertices 
struct Graph* createGraph(int V) 
{ 
    struct Graph* graph =  
        (struct Graph*) malloc(sizeof(struct Graph)); 
    graph->V = V; 

    // Create an array of adjacency lists.  Size of  
    // array will be V 
    graph->array =  
      (struct AdjList*) malloc(V * sizeof(struct AdjList)); 

    // Initialize each adjacency list as empty by  
    // making head as NULL 
    int i; 
    for (i = 0; i < V; ++i) 
        graph->array[i].head = NULL; 

    return graph; 
} 

// Adds an edge to an undirected graph 
void addEdge(struct Graph* graph, int src, int dest) 
{ 
    // Add an edge from src to dest.  A new node is  
    // added to the adjacency list of src.  The node 
    // is added at the begining 
    struct AdjListNode* newNode = newAdjListNode(dest); 
    newNode->next = graph->array[src].head; 
    graph->array[src].head = newNode; 

    // Since graph is undirected, add an edge from 
    // dest to src also 
    newNode = newAdjListNode(src); 
    newNode->next = graph->array[dest].head; 
    graph->array[dest].head = newNode; 
} 

// A utility function to print the adjacency list  
// representation of graph 
void printGraph(struct Graph* graph) 
{ 
    int v; 
    for (v = 0; v < graph->V; ++v) 
    { 
        struct AdjListNode* pCrawl = graph->array[v].head; 
        printf("\n Adjacency list of vertex %d\n head ", v); 
        while (pCrawl) 
        { 
            printf("-> %d", pCrawl->dest); 
            pCrawl = pCrawl->next; 
        } 
        printf("\n"); 
    } 
} 

// Driver program to test above functions 
int main() 
{ 
    // create the graph given in above fugure 
    int V = 5; 
    struct Graph* graph = createGraph(V); 
    addEdge(graph, 0, 1); 
    addEdge(graph, 0, 4); 
    addEdge(graph, 1, 2); 
    addEdge(graph, 1, 3); 
    addEdge(graph, 1, 4); 
    addEdge(graph, 2, 3); 
    addEdge(graph, 3, 4); 

    // print the adjacency list representation of the above graph 
    printGraph(graph); 

    return 0; 
}
#包括
#包括
//表示邻接列表节点的结构
结构AdjListNode
{ 
int dest;
结构AdjListNode*下一步;
}; 
//表示邻接列表的结构
结构调整列表
{ 
结构AdjListNode*头;
}; 
//表示图形的结构。图表
//是邻接列表的数组。
//数组的大小为V(顶点数
//(在图表中)
结构图
{ 
INTV;
结构调整列表*数组;
}; 
//用于创建新邻接列表节点的实用程序函数
结构AdjListNode*newAdjListNode(int dest)
{ 
结构AdjListNode*新节点=
(struct AdjListNode*)malloc(sizeof(struct AdjListNode));
newNode->dest=dest;
newNode->next=NULL;
返回newNode;
} 
//创建V顶点图的实用函数
结构图*createGraph(int V)
{ 
结构图*图=
(结构图*)malloc(sizeof(结构图));
图形->V=V;
//创建邻接列表数组。的大小
//数组将为V
图形->数组=
(结构调整列表*)malloc(V*sizeof(结构调整列表));
//通过将每个邻接列表初始化为空
//使头部为空
int i;
对于(i=0;i数组[i]。head=NULL;
返回图;
} 
//将边添加到无向图
void addEdge(结构图*图,int src,int dest)
{ 
//将边从src添加到dest。将创建一个新节点
//添加到src的邻接列表中。节点
//是在开头添加的
结构AdjListNode*newNode=newAdjListNode(dest);
newNode->next=graph->array[src].head;
图形->数组[src].head=newNode;
//因为图形是无向的,所以从
//目的地至src
newNode=newAdjListNode(src);
新建节点->下一步=图形->数组[dest].head;
图形->数组[dest].head=newNode;
} 
//打印邻接列表的实用函数
//图的表示
void printGraph(结构图*图形)
{ 
INTV;
对于(v=0;vv;++v)
{ 
结构AdjListNode*pCrawl=graph->array[v].head;
printf(“\n顶点%d\n头的邻接列表”,v);
while(pCrawl)
{ 
printf(“->%d”,pCrawl->dest);
pCrawl=pCrawl->next;
} 
printf(“\n”);
} 
} 
//用于测试上述功能的驱动程序
int main()
{ 
//创建上图中给出的图表
int V=5;
结构图*Graph=createGraph(V);
加法(图,0,1);
加法(图,0,4);
附录(图1,2);
附录(图1,3);
附录(图1,4);
附录(图2,3);
附录(图3、4);
//打印上图的邻接列表表示形式
印刷图形;
返回0;
}
在以下代码的功能中,当启用
newNode->next
时 分配了
数组[src]。头
。这意味着
newNode
array[src]。head
。但是在声明之后
graph->array[src].head=newNode,顺序是相反的
当我们测试结果时。有人能给我解释一下吗?谢谢

#include <stdio.h> 
#include <stdlib.h> 

// A structure to represent an adjacency list node 
struct AdjListNode 
{ 
    int dest; 
    struct AdjListNode* next; 
}; 

// A structure to represent an adjacency list 
struct AdjList 
{ 
    struct AdjListNode *head;  
}; 

// A structure to represent a graph. A graph 
// is an array of adjacency lists. 
// Size of array will be V (number of vertices  
// in graph) 
struct Graph 
{ 
    int V; 
    struct AdjList* array; 
}; 

// A utility function to create a new adjacency list node 
struct AdjListNode* newAdjListNode(int dest) 
{ 
    struct AdjListNode* newNode = 
     (struct AdjListNode*) malloc(sizeof(struct AdjListNode)); 
    newNode->dest = dest; 
    newNode->next = NULL; 
    return newNode; 
} 

// A utility function that creates a graph of V vertices 
struct Graph* createGraph(int V) 
{ 
    struct Graph* graph =  
        (struct Graph*) malloc(sizeof(struct Graph)); 
    graph->V = V; 

    // Create an array of adjacency lists.  Size of  
    // array will be V 
    graph->array =  
      (struct AdjList*) malloc(V * sizeof(struct AdjList)); 

    // Initialize each adjacency list as empty by  
    // making head as NULL 
    int i; 
    for (i = 0; i < V; ++i) 
        graph->array[i].head = NULL; 

    return graph; 
} 

// Adds an edge to an undirected graph 
void addEdge(struct Graph* graph, int src, int dest) 
{ 
    // Add an edge from src to dest.  A new node is  
    // added to the adjacency list of src.  The node 
    // is added at the begining 
    struct AdjListNode* newNode = newAdjListNode(dest); 
    newNode->next = graph->array[src].head; 
    graph->array[src].head = newNode; 

    // Since graph is undirected, add an edge from 
    // dest to src also 
    newNode = newAdjListNode(src); 
    newNode->next = graph->array[dest].head; 
    graph->array[dest].head = newNode; 
} 

// A utility function to print the adjacency list  
// representation of graph 
void printGraph(struct Graph* graph) 
{ 
    int v; 
    for (v = 0; v < graph->V; ++v) 
    { 
        struct AdjListNode* pCrawl = graph->array[v].head; 
        printf("\n Adjacency list of vertex %d\n head ", v); 
        while (pCrawl) 
        { 
            printf("-> %d", pCrawl->dest); 
            pCrawl = pCrawl->next; 
        } 
        printf("\n"); 
    } 
} 

// Driver program to test above functions 
int main() 
{ 
    // create the graph given in above fugure 
    int V = 5; 
    struct Graph* graph = createGraph(V); 
    addEdge(graph, 0, 1); 
    addEdge(graph, 0, 4); 
    addEdge(graph, 1, 2); 
    addEdge(graph, 1, 3); 
    addEdge(graph, 1, 4); 
    addEdge(graph, 2, 3); 
    addEdge(graph, 3, 4); 

    // print the adjacency list representation of the above graph 
    printGraph(graph); 

    return 0; 
}
这是正确的。函数
addEdge
将在列表的开头插入新节点,您已经从测试输出中确认了这一点

这一行:

newNode->next = graph->array[dest].head; 
使新节点的
next
指针指向当前列表的开头(在更新列表之前)

那么这一行:

graph->array[dest].head = newNode; 
更新列表的开头以指向刚添加的新节点

现在,列表如下所示:

[head == new-node] -> [... state of list before addEdge was called ...]

在graph->array[dest]之后不是head==[new node]而不是head->[new node],head=newNode??如果head==新节点,我们如何将图形->数组[]。head链接到我们添加的所有节点??我不理解你的问题。此函数所做的只是将新节点添加到列表的开头,指定从src到dest的边。然后以类似的方式从dest向src添加一条边。我的意思是,如果我们不断更新head指针,那么如果我们想要打印列表,我们如何获得原始指针?因为当添加所有边时,头部点是列表每行中的最后一个节点。当添加所有边时,头部点是添加的最后一个节点。。。这是列表中的第一个节点。在为特定src边添加任何边之前,没有边,因此原始头指针为空。我不知道你为什么关心指针的变化。您的所有数据都在该列表中。您可以遍历列表(如
printGraph
中的内部循环)以访问所有数据。