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


全局变量
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 }

浙公网安备 33010602011771号