在 C 中实现具有邻接表的图

Posted

技术标签:

【中文标题】在 C 中实现具有邻接表的图【英文标题】:Implementing a graph with adjacency list in C 【发布时间】:2019-09-07 23:28:23 【问题描述】:

我现在正在学习图,当我从在线教学资源中阅读到使用邻接列表实现图时,我对addEdge 函数感到困惑。

addEdge(graph, 0, 1) 执行时,会创建值为 1 的节点,然后将 newNode->next 赋值为 NULL 的 graph->array[0].head。之后,graph->array[0].head 被分配了newNode。然后节点 0 和 1 连接,在函数的下半部分,它会反过来。我不知道这种方法如何连接两个节点。

谁能给我解释一下?

#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; 

【问题讨论】:

你的图是无向的,所以如果 U 连接到 V,那么还有一个从 V 到 U 的连接。你可以对邻接矩阵做同样的事情,你会在 adj[U][V]adj[V][U]。还是您对保存相邻节点的链表有疑问? 问题不清楚。您的程序是否输出意外数据? 程序是对的。程序不是我写的。我只是对 addEdge 函数感到困惑。 一条无向边 (a, b) 可以被视为一对有向边 ((a, b), (b, a))。 顺便说一下,这种逻辑在 C++ 中更容易实现,它为您提供了丰富的“容器类”库,这样您就不必做太多容易出错的事情“指针旋转” ... 【参考方案1】:

看起来很简单 您实际上并没有将一个节点链接到另一个节点您只是在创建一个列表,其中包含该元素已连接到该元素

更多解释:--

打电话

addEdge(graph, 0,1);

那么这个函数正在创建一个名称为 (dest) 的简单节点

struct AdjListNode* newNode = newAdjListNode(dest);

作为节点,你首先将newNode的下一个ptr分配给Source('src')节点

newNode->next = graph->array[src].head; 

然后你将 SrcNode 分配给 newNode(非常像我们用来交换元素的方式)

graph->array[src].head = newNode; 

到目前为止,您已经链接了 Src 和 Dest 节点(但只有一种方式)。

现在从 Dest 到 Src 重复上述过程,使其成为双向路径。

解释2:--

addEdge(graph, 0, 1); 

在这一行之后评论所有内容 并添加

printf(" %d \n",graph->array[0].head->dest);
printf(" %d \n",graph->array[1].head->dest);

首先将输出 1 秒将输出 0

即使在 BFS 或 DFS 或其他方式中遍历时,我们也将需要我们实际上并不需要连接它们的列表..'

希望你明白!!!! 如有错误请指正..????

【讨论】:

【参考方案2】:
You may like to refer this other approach too :

//WAP to represent an un-directed graph using Adjacency List.
#include<stdio.h>
#include<stdlib.h>
struct ListNode

  int vertexNo;
  struct ListNode* next;
;
struct Graph

 int V;
 int E;
 struct ListNode** Adj;
;

struct ListNode* createNode(int v) 

  struct ListNode* newNode = (struct ListNode*)malloc(sizeof(struct ListNode));
  newNode->vertexNo = v;
  newNode->next = NULL;
  return newNode;


void insertNode_atEnd(struct ListNode **start, int val)   //Insert a node with vertexNo=val at end of SLL

 struct ListNode *temp,*t;
 temp=createNode(val);
 if(*start == NULL)
  *start = temp;
 else
 
  t=*start;
  
  while(t->next!=NULL)
   t=t->next;
   
  t->next=temp;
 


void viewList(struct ListNode **start)

 struct ListNode *t;
 if(*start ==NULL)
  printf("Isolated Vertex");
 else
 
  t=*start;
  while(t!=NULL) 
  
   printf("%d\t",t->vertexNo);
   t=t->next;    
  
 


struct Graph *createGraph(int V,int E)

 struct Graph *G = (struct Graph*)malloc(sizeof(struct Graph));
 if(!G)
 
  printf("Memory Error");
  return NULL;
 
 G->V = V;
 G->E = E;
 G->Adj = (struct ListNode**)malloc((G->V)*sizeof(struct ListNode));
 
 for(int i=0;i<G->V;i++)
  
    G->Adj[i] = NULL;
  
  return G;


void adjMatrixOfGraph(struct Graph *G)

  int u,v;
     printf("Enter node no. in a pair that connects an edge");
     for(int i=0;i<G->E;i++)
     
      scanf("%d %d" , &u,&v); 
      insertNode_atEnd(&(G->Adj[u]),v); 
      insertNode_atEnd(&(G->Adj[v]),u); //for undirected graph only
     
     
     printf("ADJACENCY LIST :\n");
     printf("VERTEX NO.\t CONNECTED NODES\n");
     for(int i=0;i<G->V;i++)
     
       printf("%d\t\t",i);
       viewList( &(G->Adj[i]) );
       printf("\n");
     
     


int main()

 int V,E;  
 printf("Enter no. of nodes & no. of edges");
 scanf("%d%d",&V,&E);
 struct Graph *G = createGraph(V,E);
 adjMatrixOfGraph(G);
 return 0;

【讨论】:

您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center。 哈哈哈,这个问题早就问过了。不过还是谢谢。

以上是关于在 C 中实现具有邻接表的图的主要内容,如果未能解决你的问题,请参考以下文章

在 C++ 中使用邻接表的图

求算法,用邻接矩阵和邻接表创建一个图,实现深度和广度搜索,菜单形式,c语言的代码。无向无权的图。

图的遍历(C语言,邻接表存储的图 - DFS,邻接矩阵存储的图 - BFS)

采用邻接表存储的图的深度优先遍历算法类似于二叉树的先序遍历,为啥是先序呢?

使用邻接表在 C++ 中实现 DFS(使用 <vector> 和链表)

图的邻接矩阵存储