广度优先搜索遍历(无向图)

全局变量

int visited[MAXVEX] = { 0 };/*访问标志数组*/

BFSTraverse函数

 1 /***************************************************
 2 * Name: BFSTraverse
 3 * Call: BFS
 4 * Called By: main
 5 * Parameter: G 邻接表
 6 * Description: 遍历图G的所有连通子图
 7 ****************************************************/
 8 void BFSTraverse(ALGraph* G)
 9 {
10     int i = 1;
11     for (i = 1; i <= G->vexnum; i++)
12     {
13         if (visited[i] == 0)
14         {
15             BFS(G, i);
16         }
17     }
18 }

BFS函数

 1 /******************************************************
 2 * Name: BFS
 3 * Call: InitLQueue, InLQueue, OutLQueue, FristAdjvex,
 4 *    NextAdjvex
 5 * Called By: BFSTraverse
 6 * Parameter: G 邻接表, v0 初始顶点
 7 * Description: 遍历图G中一个以顶点v0开始的连通子图
 8 *******************************************************/
 9 void BFS(ALGraph* G, int v0)
10 {
11     int v = 0;/*保存在队列中的顶点信息*/
12     int adjvex = 0;/*邻接顶点*/
13     LQueue* Q = (LQueue*)calloc(1, sizeof(LQueue));/*队列指针*/
14     ArcNode* P = NULL;
15 
16     printf("%c", G->vex[v0].vexdata);
17     visited[v0] = 1;
18     InitLQueue(Q);
19     InLQueue(Q, v0);
20     /*当队列非空*/
21     while (Q->front != Q->rear)
22     {
23         OutLQueue(Q, &v);
24         adjvex = FristAdjvex(G, v);
25         /*当邻接顶点adjvex存在,即不为0*/
26         while (adjvex)
27         {
28             /*当邻接顶点adjvex未访问过*/
29             if (visited[adjvex] == 0)
30             {
31                 printf("%c", G->vex[adjvex].vexdata);
32                 visited[adjvex] = 1;
33                 InLQueue(Q, adjvex);
34             }
35             adjvex = NextAdjvex(G, v, adjvex);
36         }
37     }
38 }

FristAdjvex函数

 1 /***************************************************
 2 * Name: FristAdjvex
 3 * Called By: BFS
 4 * Parameter: G 邻接表, v0 顶点
 5 * return: 若vex顶点的首个邻接顶点存在,则返回这个邻接顶点在
 6 *         顶点表中的下标;否则返回0
 7 ****************************************************/
 8 int FristAdjvex(ALGraph* G, int v0)
 9 {
10     if (G->vex[v0].head)
11     {
12         return G->vex[v0].head->adjvex;
13     }
14     return 0;
15 }

NextAdjvex函数

 1 /***************************************************
 2 * Name: NextAdjvex
 3 * Called By: BFS
 4 * Parameter: G 邻接表, v0 顶点, adjvex 邻接顶点
 5 * return: 查找与顶点vex邻接的adjvex顶点的下一个与顶点vex
 6 *         邻接的顶点,返回其在顶点表中的位置下标,若下一邻接
 7 *         顶点不存在,则返回0
 8 ****************************************************/
 9 int NextAdjvex(ALGraph* G, int v0, int adjvex)
10 {
11     ArcNode* P = G->vex[v0].head;
12     /*定位到顶点v0的邻接顶点adjvex*/
13     while (P && P->adjvex != adjvex)
14     {
15         P = P->next;
16     }
17     /*当v0的下一邻接顶点存在时*/
18     if (P && P->next)
19     {
20         return P->next->adjvex;
21     }
22     return 0;
23 }

源代码

  1 /************************************************************
  2 * Name: 广度优先搜索遍历(无向图)
  3 * Date: 2022.01.23
  4 * Author: 吕辉
  5 * Description: 广度优先搜索(Breadth Frist Search)类似树的按层次遍
  6 *              历;代码采用邻接表来存储无向图,使用链式队列来保存顶点,
  7 *              通过全局变量visited数组来标记顶点是否已被遍历
  8 *************************************************************/
  9 #define _CRT_SECURE_NO_WARNINGS
 10 #include <stdio.h>
 11 #include <stdlib.h>
 12 
 13 #define MAXVEX 20
 14 /*邻接表的抽象数据结构*/
 15 typedef struct ArcNode
 16 {
 17     int adjvex;
 18     struct ArcNode* next;
 19 }ArcNode;/*边表*/
 20 
 21 typedef struct VexNode
 22 {
 23     char vexdata;
 24     ArcNode* head;
 25 }VexNode;/*顶点表*/
 26 
 27 typedef struct
 28 {
 29     int vexnum;/*顶点数*/
 30     int arcnum;/*弧数*/
 31     VexNode vex[MAXVEX];
 32 }ALGraph;/*邻接表*/
 33 
 34 /*链队列的抽象数据结构*/
 35 typedef struct QNode
 36 {
 37     int data;
 38     struct QNode* next;
 39 }QNode;/*队列结点*/
 40 
 41 typedef struct
 42 {
 43     QNode* front;
 44     QNode* rear;
 45 }LQueue;/*链队列*/
 46 
 47 int visited[MAXVEX] = { 0 };/*访问标志数组*/
 48 
 49 /*队列相关函数*/
 50 void InitLQueue(LQueue* Q);
 51 void InLQueue(LQueue* Q, int data);
 52 void OutLQueue(LQueue* Q, int* data);
 53 /*邻接表相关函数*/
 54 void CreateGraph(ALGraph* G);
 55 int LocateVex(ALGraph* G, char vex);
 56 /*深度优先遍历相关函数*/
 57 void BFS(ALGraph* G, int v0);
 58 int FristAdjvex(ALGraph* G, int v0);
 59 int NextAdjvex(ALGraph* G, int v0, int adjvex);
 60 void BFSTraverse(ALGraph* G);
 61 
 62 int main(void)
 63 {
 64     ALGraph G;
 65     CreateGraph(&G);
 66     BFSTraverse(&G);
 67     system("pause");
 68     return 0;
 69 }
 70 /***************************************************
 71 * Name: InitLQueue
 72 * Called By: BFS
 73 * Parameter: Q 链队列
 74 * Description: 初始化队列
 75 ****************************************************/
 76 void InitLQueue(LQueue* Q)
 77 {
 78     QNode* P = (QNode*)calloc(1, sizeof(QNode));
 79     Q->front = P;
 80     Q->rear = P;
 81     P = NULL;
 82     free(P);
 83 }
 84 /***************************************************
 85 * Name: InLQueue
 86 * Called By: BFS
 87 * Parameter: Q 链队列, data 入队元素
 88 * Description: 把元素data入队
 89 ****************************************************/
 90 void InLQueue(LQueue* Q, int data)
 91 {
 92     QNode* P = (QNode*)calloc(1, sizeof(QNode));
 93     P->data = data;
 94     Q->rear->next = P;
 95     Q->rear = P;
 96 }
 97 /***************************************************
 98 * Name: OutLQueue
 99 * Called By: BFS
100 * Parameter: Q 链队列, data 出队元素
101 * Description: 出队首元素,并保存在data引用地址中
102 ****************************************************/
103 void OutLQueue(LQueue* Q, int* data)
104 {
105     QNode* P = NULL;
106     if (Q->front == Q->rear)
107     {
108         printf("\n出队失败,空队列\n");
109         exit(-1);
110     }
111     else
112     {
113         P = Q->front->next;
114         Q->front->next = P->next;
115         (*data) = P->data;
116         free(P);
117         /*链队列仅有一个元素结点时,删除后还需要修改尾指针*/
118         if (Q->front->next == NULL)
119         {
120             Q->rear = Q->front;
121         }
122     }
123 }
124 /***************************************************
125 * Name: CreateGraph
126 * Call: LocateVex
127 * Called By: main
128 * Parameter: G 邻接表
129 * Description: 创建邻接表
130 ****************************************************/
131 void CreateGraph(ALGraph* G)
132 {
133     int i = 1;
134     int j = 1;
135     int k = 1;
136     char vex1 = '\0';
137     char vex2 = '\0';
138     ArcNode* P = NULL;
139     ArcNode* Pre = NULL;
140 
141     printf("请输入顶点数和弧数(逗号分隔):");
142     scanf("%d%*c%d", &G->vexnum, &G->arcnum);
143     for (i = 1; i <= G->vexnum; i++)
144     {
145         printf("请输入第%d个顶点:", i);
146         scanf(" %c", &G->vex[i].vexdata);
147         G->vex[i].head = NULL;
148     }
149     for (k = 1; k <= G->arcnum; k++)
150     {
151         printf("请输入第%d条弧的两端点(逗号分隔):", k);
152         scanf(" %c%*c%c", &vex1, &vex2);
153         i = LocateVex(G, vex1);
154         j = LocateVex(G, vex2);
155         /*把弧信息链接到其中一端的顶点表中*/
156         P = (ArcNode*)calloc(1, sizeof(ArcNode));
157         P->adjvex = j;
158         if (G->vex[i].head == NULL)
159         {
160             G->vex[i].head = P;
161         }
162         else
163         {
164             Pre = G->vex[i].head;
165             while (Pre->next)
166             {
167                 Pre = Pre->next;
168             }
169             Pre->next = P;
170             /*把弧信息链接到另一端的顶点表*/
171             P = (ArcNode*)calloc(1, sizeof(ArcNode));
172             P->adjvex = i;
173             if (G->vex[j].head == NULL)
174             {
175                 G->vex[j].head = P;
176             }
177             else
178             {
179                 Pre = G->vex[j].head;
180                 while (Pre->next)
181                 {
182                     Pre = Pre->next;
183                 }
184                 Pre->next = P;
185             }
186         }
187     }/*for循环*/
188 }
189 /***************************************************
190 * Name: LocateVex
191 * Called By: Create
192 * Parameter: G 邻接表, vex 顶点
193 * return : 若顶点表中存在该顶点则返回其在顶点表中的位置下标;
194 *      否则返回0
195 ****************************************************/
196 int LocateVex(ALGraph* G, char vex)
197 {
198     int i = 1;
199     for (i = 1; i <= G->vexnum; i++)
200     {
201         if (G->vex[i].vexdata == vex)
202         {
203             return i;
204         }
205     }
206     return 0;
207 }
208 /******************************************************
209 * Name: BFS
210 * Call: InitLQueue, InLQueue, OutLQueue, FristAdjvex,
211 *       NextAdjvex
212 * Called By: BFSTraverse
213 * Parameter: G 邻接表, v0 初始顶点
214 * Description: 遍历图G中一个以顶点v0开始的连通子图
215 *******************************************************/
216 void BFS(ALGraph* G, int v0)
217 {
218     int v = 0;/*保存在队列中的顶点信息*/
219     int adjvex = 0;/*邻接顶点*/
220     LQueue* Q = (LQueue*)calloc(1, sizeof(LQueue));/*队列指针*/
221     ArcNode* P = NULL;
222 
223     printf("%c", G->vex[v0].vexdata);
224     visited[v0] = 1;
225     InitLQueue(Q);
226     InLQueue(Q, v0);
227     /*当队列非空*/
228     while (Q->front != Q->rear)
229     {
230         OutLQueue(Q, &v);
231         adjvex = FristAdjvex(G, v);
232         /*当邻接顶点adjvex存在,即不为0*/
233         while (adjvex)
234         {
235             /*当邻接顶点adjvex未访问过*/
236             if (visited[adjvex] == 0)
237             {
238                 printf("%c", G->vex[adjvex].vexdata);
239                 visited[adjvex] = 1;
240                 InLQueue(Q, adjvex);
241             }
242             adjvex = NextAdjvex(G, v, adjvex);
243         }
244     }
245 }
246 /***************************************************
247 * Name: FristAdjvex
248 * Called By: BFS
249 * Parameter: G 邻接表, v0 顶点
250 * return: 若vex顶点的首个邻接顶点存在,则返回这个邻接顶点在
251 *       顶点表中的下标;否则返回0
252 ****************************************************/
253 int FristAdjvex(ALGraph* G, int v0)
254 {
255     if (G->vex[v0].head)
256     {
257         return G->vex[v0].head->adjvex;
258     }
259     return 0;
260 }
261 /***************************************************
262 * Name: NextAdjvex
263 * Called By: BFS
264 * Parameter: G 邻接表, v0 顶点, adjvex 邻接顶点
265 * return: 查找与顶点vex邻接的adjvex顶点的下一个与顶点vex
266 *         邻接的顶点,返回其在顶点表中的位置下标,若下一邻接
267 *         顶点不存在,则返回0
268 ****************************************************/
269 int NextAdjvex(ALGraph* G, int v0, int adjvex)
270 {
271     ArcNode* P = G->vex[v0].head;
272     /*定位到顶点v0的邻接顶点adjvex*/
273     while (P && P->adjvex != adjvex)
274     {
275         P = P->next;
276     }
277     /*当v0的下一邻接顶点存在时*/
278     if (P && P->next)
279     {
280         return P->next->adjvex;
281     }
282     return 0;
283 }
284 /***************************************************
285 * Name: BFSTraverse
286 * Call: BFS
287 * Called By: main
288 * Parameter: G 邻接表
289 * Description: 遍历图G的所有连通子图
290 ****************************************************/
291 void BFSTraverse(ALGraph* G)
292 {
293     int i = 1;
294     for (i = 1; i <= G->vexnum; i++)
295     {
296         if (visited[i] == 0)
297         {
298             BFS(G, i);
299         }
300     }
301 }
View Code
posted @ 2022-01-23 03:24  吕辉  阅读(174)  评论(0)    收藏  举报