廣度優先算法又稱寬度優先搜索,是一種簡便的圖的搜索算法之一。搜索方式大致是這樣的:







直到搜索到目標結點(結點就是那些圓球球,其中有一個或者多個是目標結點)或者搜完了整個圖都沒找到目標結點就停止搜索。
實現這個要是想用像深度優先算法那樣函數套函數那樣是難以實現的(至少我實現不了)。
像這樣的:
求問從A到B的最短路徑的結點數是多少?

這道題很簡單嘛,肯定是A-C-B啊,答案是3啊。那怎樣用C語言實現呢?
深搜的話:一條路一條路讀取,取結點數最小的,也可以,但是問題來了,當結點數特別多,圖非常“遼闊”時,怎么辦呢?
用廣搜啦!
這里設A的標志為0(這樣好些代碼嘛),其他的以此類推,所以路徑A-C-B就是0-2-1啦
根據路是不是相同的,我們可以創建一個布爾型二維數組way,way[w1][w2]=1代表從w1可以到達w2,=0時則代表不能,注意,因為我們是不會走回頭路的,所以所有路都是單向的,比如c->b是可以的,但b->c是不可以的
_Bool way[6][6]={
{0,0,1,1,1,0},
{0,0,0,0,0,0},
{0,1,0,0,0,0},
{0,0,0,0,0,1},
{0,0,0,0,0,1},
{0,1,0,0,0,0},
};
創建一個step數組,初始值為0,step[0]代表A的結點數,step[1]代表B的結點數,因為A只有一個結點所以step[0]=1,儲存列出了幾層子結點,也就是目前所有路徑的結點數
創建一個隊列,比如叫que(其實就是個數組嘛)
簡單講下隊列的概念:有隊首(head)和隊尾(tail)兩個指針,分別指着隊列的第一個元素與最后一個元素。隊列只允許從隊尾加入隊伍,從隊首退出隊伍。
此時head=tail=0:
在隊列que中加入A結點的標志0,步驟是將tail+=1並且que[tail]=0(如圖所示)

然后搜索A的子結點,例如這樣:
循環(i=0;i<=5;i++)//因為共有6個結點
如果(way[que[head+1]][i]==1)把子結點加入隊列;
加入隊列的方法就是:
tail+=1;
que[tail]=子結點標志;
注意要讓子結點的結點數+=它的父結點的結點數
最后效果如圖

當循環完畢以后呢,就等於把A的子結點全找出來了,列出了一整層結點,刪去第一個結點,step[2]和[3]和[4]都=step[0]+1,head-=1,那樣head指的就是A的子結點C(標志2)了如圖

繼續判斷,搜索2的子結點,並且加入隊列,再刪去2,搜索3的子結點……直到最后tail指針指的是B(標志1),則輸出step[1](B的標志是1),就是最短路徑數。如果head=tail了,說明隊列為空,而且沒找到答案,所以就沒有可以到達目標結點的路,輸出什么的就隨你了。
附上此題答案:
#include <stdio.h> #include <string.h> _Bool way[6][6]={ {0,0,1,1,1,0}, {0,0,0,0,0,0}, {0,1,0,0,0,0}, {0,0,0,0,0,1}, {0,0,0,0,0,1}, {0,1,0,0,0,0}, }; int main() { int que[101],head=0,tail=1,i,step[6]; memset(step,0,sizeof(step));//初始化步數數組 que[1]=0;//初始化隊首 step[0]=1; //結點A的步數為1 do { for(i=0;i<=5;i++) { if(way[que[head+1]][i]==1) { tail++; que[tail]=i; step[i]=step[que[head+1]]+1; if(que[tail]==1) { printf("%d",step[1]); return 0; } } } head++; }while(head<tail);//當隊列不為空 printf("no answer!"); return 0; }
