圖之廣度優先搜尋(BFS)
阿新 • • 發佈:2019-01-04
我們先看下圖的廣度優先搜尋的定義,然後可以感覺很熟悉,對的,那就是二叉樹層次遍歷裡的方法,可以參考,我的文章,二叉樹之層次遍歷(二)
定義:
它的基本思想就是:首先訪問起始頂點v,接著由v出發,依次訪問v的各個未訪問過的鄰接頂點w1,w2,…,wi,然後再依次訪問w1,w2,…,wi的所有未被訪問過的鄰接頂點;再從這些訪問過的頂點出發,再訪問它們所有未被訪問過的鄰接頂點……依次類推,直到圖中所有頂點都被訪問過為止。
廣度優先搜尋是一種分層的查詢過程,每向前走一步可能訪問一批頂點,不像深度優先搜尋那樣有往回退的情況,因此它不是一個遞迴的演算法。為了實現逐層的訪問,演算法必須藉助一個輔助佇列,以記錄正在訪問的頂點的下一層頂點。
例子:
第一層:A;
第二層:C,D,F;
第三層:B,G;
第四層:E;
程式碼:
#include<stdio.h> #include<stdlib.h> #include <malloc.h> #include <string.h> #define MAX 10 #define nLENGTH(a) (sizeof(a)/sizeof(a[0])) #define eLENGTH(a) ( sizeof(a) / sizeof(char) )/ ( sizeof(a[0]) / sizeof(char) ) typedef struct _graph { char vexs[MAX]; // 頂點集合 int vexnum; // 頂點數 int edgnum; // 邊數 int matrix[MAX][MAX]; // 鄰接矩陣 }Graph, *PGraph; //建立佇列節點 typedef struct node { char data; struct node *next; }linklist; typedef struct list { linklist *front,*rear; int num; }link,*linkqueue; //指向節點的位置 int point_node(PGraph g,char c) { for(int i=0;i<g->vexnum;i++) { if(g->vexs[i]==c) { return i; } } return -1; } PGraph create_graph(char b[][2],char a[],int n,int e) { char c1,c2; //邊的2個頂點 PGraph g; //矩陣 g=(PGraph)malloc(sizeof(Graph)); //memset()第一個引數 是地址,第二個引數是開闢空間的初始值,第三個引數是開闢空間的大小 memset(g, 0, sizeof(Graph)); printf("頂點個數:\n");//頂點數 g->vexnum=n; printf("%d\n",g->vexnum); printf("邊個數:\n");//邊數 g->edgnum=e; printf("%d\n",g->edgnum); //初始化頂點 for(int j=0;j<g->vexnum;j++) { g->vexs[j]=a[j]; } for(int i=0;i<g->edgnum;i++) { int p1,p2; c1=b[i][0]; c2=b[i][1]; p1=point_node(g, c1); p2=point_node(g, c2); if (p1==-1 || p2==-1) { printf("input error: invalid edge!\n"); free(g); continue; } g->matrix[p1][p2]=1; g->matrix[p2][p1]=1; } return g; } //返回與v相鄰的第一個頂點 int first_node(PGraph g,int v) { int i; for(i=0;i<g->vexnum;i++) { if(g->matrix[v][i]!=0) return i; } return -1; } //返回與v相鄰的下一個頂點 int next_node(PGraph g,int v,int w) { int i; for(i=w+1;i<g->vexnum;i++) { if(g->matrix[v][i]!=0) return i; } return -1; } //初始化空隊 void InitEmpty(linkqueue &q) { q->front=q->rear=(linklist*)malloc(sizeof(linklist)); q->front->next=NULL; q->rear->next=NULL; } //置空隊 void SetEmptyQueue(linkqueue &q) { q->front->next=NULL; q->front=q->rear; } //判斷空隊 int IsEmpty(linkqueue &q) { if(q->front==q->rear) { return 1; }else{ return 0; } //return ((q->front==q->rear)?1:0); } //元素入隊 int InQueue(linkqueue &q,char e) { q->rear->next=(linklist*)malloc(sizeof(linklist));; q->rear=q->rear->next; q->rear->data=e; q->rear->next=NULL; q->num++; return 0; } //元素出隊 int OutQueue(linkqueue &q) { int e; linklist *p; if(IsEmpty(q)) { printf("空隊!\n"); return 0; } p=q->front; q->front=p->next; e=q->front->data; free(p); q->num--; return e; } void BFS(PGraph g,char start) { //指向鏈佇列 linkqueue m; m=(linkqueue)malloc(sizeof(link)); InitEmpty(m); //初始化佇列,為佇列分配記憶體 SetEmptyQueue(m); //使佇列為空隊 int visit[MAX]={0}; //標記頂點 int i=point_node(g,start); if(!visit[i]) { InQueue(m,g->vexs[i]); visit[i]=1; } while(!IsEmpty(m)) { char b=OutQueue(m); int j=point_node(g,b); printf("%c\t",b); for(int w=first_node(g,j);w>=0;w=next_node(g,j,w)) { if(!visit[w]) { visit[w]=1; InQueue(m,g->vexs[w]); } } } } //測試 int main() { int i,j; PGraph gp; //測試用例 char a[]={'A', 'B', 'C', 'D', 'E', 'F', 'G'}; char b[][2]={ {'A', 'C'}, {'A', 'D'}, {'A', 'F'}, {'B', 'C'}, {'C', 'D'}, {'E', 'G'}, {'F', 'G'}}; //測試用例 int n=nLENGTH(a); int e=eLENGTH(b); gp=create_graph(b,a,n,e); //列印矩陣 for (i = 0; i < gp->vexnum; i++) { for (j = 0; j < gp->vexnum; j++) printf("%d ", gp->matrix[i][j]); printf("\n"); } //廣度優先搜尋圖 printf("廣度優先搜尋圖:\n"); BFS(gp,'A'); return 0; }