图的邻接表存储表示,图的深度优先和广度优先遍历

Posted robin_X

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图的邻接表存储表示,图的深度优先和广度优先遍历相关的知识,希望对你有一定的参考价值。

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 
  4 #define MAX_VERTAX_SIZE 20
  5 #define OK 1
  6 #define ERROR 0
  7 
  8 typedef int Status;
  9 typedef char ElemType;
 10 
 11 typedef struct EageNode{
 12     int adjacentVertax;
 13     struct EageNode* nextAdjacentVertax;
 14 }EageNode, *EageNodePtr;
 15 
 16 typedef struct VertaxNode{
 17     ElemType data;
 18     EageNodePtr firstEage;
 19 }VertaxNode;
 20 
 21 typedef struct GraphAL{
 22     VertaxNode VertaxArray[MAX_VERTAX_SIZE];
 23     int vertaxNum;
 24     int eageNum;
 25 }GraphAL;
 26 
 27 //定义队列结构,用于图的广度优先遍历
 28 typedef struct QueueNode{
 29     ElemType data;
 30     struct QueueNode* next;
 31 }QueueNode, *QueueNodePtr;
 32 typedef struct Queue{
 33     QueueNodePtr front;
 34     QueueNodePtr rear;
 35 }Queue;
 36 Status InitQueue(Queue* Q){
 37     Q->front = (QueueNodePtr)malloc(sizeof(struct QueueNode));
 38     if( !Q->front )
 39         return ERROR;
 40     Q->rear = Q->front;
 41     Q->rear->next = NULL;
 42     return OK;
 43 }
 44 Status EnterQueue(Queue *q, ElemType value){
 45     QueueNode* n;
 46     n = (QueueNode*)malloc(sizeof(struct QueueNode));
 47     if( !n )
 48         return ERROR;
 49     n->data = value;
 50     n->next = q->rear->next;
 51     q->rear->next = n;
 52     q->rear = n;
 53     return OK;
 54 }
 55 Status DeleteQueue(Queue* q,ElemType* value){
 56     if( q->front == q->rear )
 57         return ERROR;
 58     QueueNode* p;
 59     p = q->front->next;
 60     *value = p->data;
 61     q->front->next = p->next;
 62     free(p);
 63     if( p == q->rear )
 64         q->rear = q->front;
 65     return OK;
 66 }
 67 int IsQueueEmpty(Queue q){
 68     return q.front == q.rear ? OK : ERROR;
 69 }
 70 /*
 71 int main(){
 72     Queue q;
 73     ElemType c;
 74     InitQueue(&q);
 75     EnterQueue(&q,‘a‘);
 76     EnterQueue(&q,‘f‘);
 77     EnterQueue(&q,‘g‘);
 78     EnterQueue(&q,‘e‘);
 79     DeleteQueue(&q,&c);
 80     printf("%c \n", c);
 81     printf("&&&&%d", IsQueueEmpty(q));
 82     DeleteQueue(&q,&c);
 83     printf("%c \n", c);
 84     return 0;
 85 }
 86 */
 87 
 88 //返回顶点v在G中的下标
 89 int LocateVertax(GraphAL G, ElemType v){
 90     int i;
 91     for( i = 0; i < G.vertaxNum; i++ ){
 92         if( G.VertaxArray[i].data == v )
 93             return i;
 94     }
 95     return -1;
 96 }
 97 //通过下标得到元素的值
 98 ElemType GetValueFromIndex(GraphAL G, int index){
 99     return G.VertaxArray[index].data;
100 }
101 //创建邻接表无向图
102 Status CreateUDG_AdjacencyList(GraphAL* G){
103     int i;
104     ElemType v,w;
105     int index_v, index_w;
106     EageNodePtr vPtr,wPtr;
107     printf("    Create Undigraph\n");
108     printf("Please enter the number of Vertax and Eage: ");
109     scanf("%d %d%*c", &(G->vertaxNum), &(G->eageNum));
110 
111     printf("ok, please input the value of %d Vertax\n", G->vertaxNum);
112     for( i = 0; i < G->vertaxNum; i++ ){
113         scanf("%c%*c", &(G->VertaxArray[i].data));
114         G->VertaxArray[i].firstEage = NULL;
115     }
116 
117     for( i = 0; i < G->eageNum; i++ ){
118         printf("ok, please input the two Vertax of Eage %d (Sepearted by Space) :", i+1);
119         scanf("%c %c%*c", &v,&w);    //一条边的两个顶点v w
120         index_v = LocateVertax(*G, v);
121         index_w = LocateVertax(*G, w);
122         wPtr = (EageNode*)malloc(sizeof(EageNode));
123         if( !wPtr )
124             return ERROR;
125         wPtr->adjacentVertax = index_w;
126         wPtr->nextAdjacentVertax = G->VertaxArray[index_v].firstEage;
127         G->VertaxArray[index_v].firstEage = wPtr;
128 
129         vPtr = (EageNode*)malloc(sizeof(EageNode));
130         if( !vPtr )
131             return ERROR;
132         vPtr->adjacentVertax = index_v;
133         vPtr->nextAdjacentVertax = G->VertaxArray[index_w].firstEage;
134         G->VertaxArray[index_w].firstEage = vPtr;
135     }
136     return OK;
137 }
138 //在图G中找v的第一个邻接顶点,找到则返回该顶点在邻接表中的位置,若没有则返回-1
139 int FirstAdjacentVertax(GraphAL G, ElemType v){
140     int index_v;
141     index_v = LocateVertax(G, v);
142     if( G.VertaxArray[index_v].firstEage == NULL )
143         return -1;
144     else
145         return (G.VertaxArray[index_v].firstEage)->adjacentVertax;
146 }
147 //在图G中找v的从w开始的下一个相邻的顶点
148 int NextAdjacentVertax(GraphAL G, ElemType v, ElemType w ){
149     int index_v,index_w;
150     EageNodePtr p;
151     index_v = LocateVertax(G, v);
152     index_w = LocateVertax(G, w);
153     if( G.VertaxArray[index_v].firstEage == NULL )
154         return -1;
155     p = G.VertaxArray[index_v].firstEage;         //p pointer to first node
156     while( p->nextAdjacentVertax != NULL ){
157         if( p->adjacentVertax == index_w )
158             return p->nextAdjacentVertax->adjacentVertax;
159         p = p->nextAdjacentVertax;
160     }
161     return -1;
162 }
163 
164 //DFS深度优先遍历图:使用递归算法,算法思想:
165 //        1:从v顶点开始,visit(v),将其设置为已遍历
166 //        2: 获得v的第一个邻接顶点w,若其存在并且没有访问过,递归遍历;
167 //        3: 获得v的从w之后的邻接点,若其存在并且没有访问过,递归遍历;直到所有都访问过
168 int visitedArray[MAX_VERTAX_SIZE];
169 void visit(ElemType c){
170     printf("%c ", c);
171 }
172 Status DFS(GraphAL G, ElemType v){
173     ElemType w;
174     visit(v);
175     visitedArray[LocateVertax(G, v)] = 1;
176     for( w = GetValueFromIndex(G, FirstAdjacentVertax(G, v)); LocateVertax(G, w) != -1; w = GetValueFromIndex(G, NextAdjacentVertax(G, v, w))){
177         if( visitedArray[LocateVertax(G, w)] != 1 )
178             DFS(G, w);
179     }
180     return OK;
181 }
182 Status DFSTraverse(GraphAL G){
183     int i;
184     for( i = 0; i < G.vertaxNum; i++ )
185         visitedArray[i] = 0;
186     for( i = 0; i < G.vertaxNum; i++ )
187         if( visitedArray[i] != 1 )
188             DFS(G, GetValueFromIndex(G, i));
189     return OK;
190 }
191 
192 
193 //BFS(Breadth First Search)
194 Status BFS(GraphAL G){
195     int i,j;
196     Queue q;
197     ElemType c;
198     InitQueue(&q);
199     for(i = 0; i < G.vertaxNum; i++)
200         visitedArray[i] = 0;
201     for(i = 0; i < G.vertaxNum; i++){    //这个for实际执行的次数是连通分量的个数
202         if( visitedArray[i] == 0 ){
203             EnterQueue(&q, G.VertaxArray[i].data);
204             visitedArray[i] = 1;
205             while( IsQueueEmpty(q) != OK ){
206                 DeleteQueue(&q, &c);
207                 visit(c);
208                 for( j = FirstAdjacentVertax(G, c); j != -1; j = NextAdjacentVertax(G, c, GetValueFromIndex(G, j))){
209                     if( visitedArray[j] == 0 ){
210                         EnterQueue(&q, GetValueFromIndex(G, j));
211                         visitedArray[j] = 1;
212                     }
213                 }
214             }
215         }
216     }
217 }
218 
219 
220 //打印无向图的邻接表
221 void PrintUDG_AdjacentList(GraphAL G){
222     int i;
223     EageNodePtr p;
224     printf("  Adjacency List \n");
225     for( i = 0; i < G.vertaxNum; i++ ){
226         printf(" %d %c ",i, G.VertaxArray[i]);
227         p = G.VertaxArray[i].firstEage;
228         while( p != NULL ){
229             printf("-->%d", p->adjacentVertax);
230             p = p->nextAdjacentVertax;
231         }
232         printf("\n");
233     }
234 }
235 int main(){
236     GraphAL G;
237     CreateUDG_AdjacencyList(&G);
238     PrintUDG_AdjacentList(G);
239 
240     printf("   DFS(Depth First Search) of UDG(Undigraph)\n");
241     DFSTraverse(G);
242 
243     printf("\n  BFS(Breadth First Search) of UDG(Undigraph)\n");
244     BFS(G);
245     return 0;
246 }

技术分享

以上是关于图的邻接表存储表示,图的深度优先和广度优先遍历的主要内容,如果未能解决你的问题,请参考以下文章

图的遍历:深度优先遍历,广度优先遍历

以邻接多重表为存储结构,实现连通无向图的深度优先遍历和广度优先遍历。

用c语言编程 1创建图的邻接矩阵和邻接表 2验证图的深度优先、广度优先遍历算法 3验证最短路径

用邻接表表示图的广度优先搜索时的存储结构,通常采用()结构来实现算法

图的深度优先遍历DFS和广度优先遍历BFS(邻接矩阵存储)超详细完整代码进阶版

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