圖的廣度優先遍歷BFS(鄰接矩陣實現)c語言
阿新 • • 發佈:2019-01-03
廣度優先遍歷也叫廣度優先搜尋(Breadth First Search)。它的遍歷規則:
- 先訪問完當前頂點的所有鄰接點。
- 先訪問的頂點的鄰接點先於後訪問頂點的鄰接點被訪問。
演算法思想:
使用佇列的資料結構(FIFO (First In First Out)),將一個頂點加入佇列,然後在佇列中刪除頂點,並且將該頂點相連的所有頂點依次加入佇列中,再迴圈處理這些頂點,直至所有頂點均被訪問。(類似樹的層序遍歷)
演算法所需:
對佇列的基本操作熟悉
程式碼實現如下:
#include<stdio.h> #include<stdlib.h> #define MAX 10 #define INFINITY 65535 #define TRUE 1 #define FALSE 0 typedef char VertexType; typedef int EdgeType; typedef int Boole; //布林型別 儲存TRUE FALSE Boole visited[MAX]; //訪問標誌陣列 typedef int QElemType; //鏈佇列的資料型別 typedef int Status; /*鄰接矩陣結構*/ typedef struct { VertexType vexs[MAX]; //頂點表 EdgeType arc[MAX][MAX]; //鄰接矩陣 可看作邊表 int numVertexes,numEdges; //頂點數和邊數 }MGraph; /*佇列結構*/ typedef struct QNode { QElemType data; struct QNode *next; }QNode,*QueuePtr; typedef struct { QueuePtr front,rear; //隊頭隊尾指標 }LinkQueue; //構造鄰接矩陣 void create(MGraph *G) { int i,j,k,w; printf("請輸入頂點數和邊數:\n"); scanf("%d%d",&G->numVertexes,&G->numEdges); fflush(stdin); for(i=0;i<G->numVertexes;i++) //建立頂點表 { printf("\n第%d個頂點",i+1); scanf("%c",&G->vexs[i]); getchar(); } for(i=0;i<G->numVertexes;i++) //矩陣初始化 for(j=0;j<G->numVertexes;j++) G->arc[i][j]=INFINITY; for(k=0;k<G->numEdges;k++) { printf("輸入邊(Vi,Vj)的上下標i,j和權w(空格隔開):"); scanf("%d%d%d",&i,&j,&w); G->arc[i][j]=w; G->arc[j][i]=G->arc[i][j]; } } //輸出鄰接矩陣 void Output(MGraph *G) { int i,j,count=0; for(i=0;i<G->numVertexes;i++) printf("\t%c",G->vexs[i]); printf("\n"); for(i=0;i<G->numVertexes;i++) { printf("%4c",G->vexs[i]); for(j=0;j<G->numVertexes;j++) { printf("\t%d",G->arc[i][j]); count++; if(count%G->numVertexes==0) printf("\n"); } } } //建立空佇列 Status InitQueue(LinkQueue &Q) { Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode)); if(!Q.front) exit(0); Q.front->next=NULL; return 1; } //入佇列 //將s作為新元素加入隊尾 Status EnQueue(LinkQueue &Q,int i) { QueuePtr s; s=(QueuePtr)malloc(sizeof(QNode)); if(!s) exit(0); s->data=i; s->next=NULL; Q.rear->next=s; Q.rear=s; return 1; } //檢驗是否為空 Status QueueEmpty(LinkQueue Q) { if(Q.front->next==NULL) return 0; else return 1; } //出佇列 Status DeQueue(LinkQueue *Q,int *i) { QueuePtr p; if(Q->front==Q->rear) return 0; p=Q->front->next; //該寫法值得商榷 //相當於p儲存第一個結點 *i=p->data; Q->front->next=p->next; if(p==Q->rear) //若隊頭是隊尾 ,刪除後將rear指向頭結點 Q->rear==Q->front; free(p); return 1; } /*廣度遍歷*/ void BFSTraverse(MGraph G) { int i,j; LinkQueue Q; for(i=0;i<G.numVertexes;i++) visited[i]=FALSE; InitQueue(Q); //&的用法?? 初始化佇列 for(i=0;i<G.numVertexes;i++) { if(!visited[i]) //未訪問過 該頂點 { visited[i]=TRUE; printf("%c->",G.vexs[i]); EnQueue(Q,i); //將其入佇列 while(!QueueEmpty(Q)) { DeQueue(&Q,&i); //將隊中元素出佇列,賦值給i for(j=0;j<G.numVertexes;j++) { if(G.arc[i][j]==1&&!visited[j]) //其他頂點與該頂點存在邊 且未訪問過 { visited[j]=TRUE; printf("%c",G.vexs[j]); EnQueue(Q,j); //入佇列 } } } } } } int main() { MGraph G; create(&G); printf("鄰接矩陣資料如下:\n"); Output(&G); printf("\n"); BFSTraverse(G); printf("\n圖遍歷完畢"); return 0; }