一、題目
根據上次隨機生成的100個頂點的無向圖和有向圖,對其進行廣度優先搜索。
二、理解廣度優先搜索
廣度優先搜索可以將其想象成水滴落入水面濺起了的一圈一圈的漣漪,是由一個起始點開始一圈一圈進行擴散搜索的。
【課上老師是這樣說的,大家想象一下,發現其實非常形象】
廣度優先搜索總是從一個起始點出發,首先擴散這個點周圍所有的鄰居,然后鄰居在去擴散鄰居的鄰居(*^-^*)...然后一直到最后將整張圖都擴散完。
三、代碼實現
對於第一次隨機生成100個頂點的圖進行了細節的修改,將每個頂點的類型改為了自定義的結構體類型,是為了可以記錄更多的頂點的信息。
1.修改了圖中頂點的類型
1 enum Color{white,red,green};//設定每個頂點的顏色,white表示還沒有碰到的,green表示在隊列中的,red表示已經完成的 2 3 struct vertextype//表示圖中的每個頂點的類型 4 { 5 int id;//每個頂點的編號 6 int pred;//每個頂點的前驅頂點 7 int dist;//每個頂點的距離 8 enum Color color;//設定頂點的狀態 9 }; 10 11 struct MGraph//鄰接矩陣表示法的結構和類型聲明 12 { 13 vertextype V[maxvertexnum];//頂點集 14 edgetype E[maxvertexnum][maxvertexnum];//邊集 15 int n,e;//頂點數,邊數 16 enum GraphType GType;//設定圖的類型 17 };
2.廣度優先算法實現
1 void bfs(MGraph *G,vertextype s) 2 { 3 int i,j,k=0; 4 for(i=0;i<100;i++)//初始化圖中所有點,使其全部為未被碰到的,以及沒有前驅,沒有距離,100表示生成圖中只有100個頂點,根據生成的圖具體定義 5 { 6 if (s.id==i) 7 { 8 continue;//跳過初始點s 9 }else 10 { 11 G->V[i].color=white; 12 G->V[i].dist=infinity; 13 G->V[i].pred=NULL; 14 //cout<<"["<<G->V[i].id<<","<<G->V[i].pred<<","<<G->V[i].color<<"]\t"; 15 } 16 } 17 s.color=green;//將初始點入隊 18 s.dist=0; 19 s.pred=NULL; 20 queue<vertextype> Q;//創建一個空隊列 21 Q.push(s);//將初始點入隊列 22 cout<<"["<<s.id<<","<<s.pred<<","<<s.color<<"]"<<endl;//此處都為打印驗證可以將其注釋 23 24 cout<<endl; 25 while(!Q.empty())//當隊列非空 26 { 27 vertextype u,v;//建立一個空頂點 28 u=Q.front();//取出隊列第一個元素 29 Q.pop();//將隊列中第一個元素刪除 30 cout<<endl; 31 cout<<"====["<<u.id<<","<<u.pred<<","<<u.color<<"]====="<<endl;//此處為打印驗證可以注釋 32 33 int i,j; 34 for(i=0;i<100;i++) 35 { 36 //v=G->V[i]; 37 if(G->E[u.id][i]==0)//在u的鄰接矩陣中找到它的鄰接頂點,當為0時跳過 38 { 39 continue; 40 } 41 else if(G->V[i].color==white) 42 { 43 G->V[i].color=green; 44 G->V[i].dist=u.dist+1; 45 G->V[i].pred=u.id; 46 Q.push(G->V[i]); 47 k++;//記錄整張圖上可以到達的點的個數 48 cout<<"["<<G->V[i].id<<","<<G->V[i].pred<<","<<G->V[i].color<<","<<G->V[i].dist<<"]\t";//此處為打印驗證可以注釋 49 } 50 } 51 u.color=red; 52 } 53 cout<<endl; 54 cout<<"================="<<k<<"==============="<<endl;//此處為打印驗證可以注釋 55 }
3.用廣度優先搜索實現找到並打印出圖上兩點之間的路徑
1 vertextype findid(MGraph *G,int id)//找到對應id的頂點,並返回,當沒有時返回空 2 { 3 return G->V[id]; 4 } 5 6 7 void printpath(MGraph *G,vertextype s,vertextype v) 8 { 9 //s為其實頂點,v為所要尋找的頂點, 10 //使用遞歸來進行每一步的更往前尋找pred 11 vertextype u; 12 //vertextype *record=new vertextype[100]; 13 int i,j; 14 if(v.id==s.id) 15 cout<<" ->"<<s.id<<" "; 16 else 17 { 18 if(v.pred==NULL) 19 { 20 cout<<"沒有頂點"<<s.id<<"到頂點"<<v.id<<"的路徑"<<endl; 21 } 22 else 23 { 24 u=findid(G,v.pred);//u表示為v的前置節點 25 printpath(G,s,u); 26 cout<<"->"<<v.id<<" "; 27 } 28 } 29 }
4.最終實現調用的main方法
1 int main() 2 { 3 ofstream myuggraph,mydggraph; 4 myuggraph.open("myuggraph.txt"); 5 6 MGraph *UGG=new MGraph(); 7 CreateMGraphUG(UGG); 8 for(int i=0;i<100;i++) 9 { 10 myuggraph<<UGG->V[i].id<<"\t"; 11 for(int j=0;j<100;j++) 12 { 13 myuggraph<<UGG->E[i][j]<<" ";//將整個鄰接矩陣寫到一個文本文件中,也是為了便於糾錯吧 14 } 15 myuggraph<<"\n"; 16 } 17 18 bfs(UGG,UGG->V[3]); 19 cout<<endl; 20 cout<<"======================"; 21 cout<<endl; 22 printpath(UGG,UGG->V[3],UGG->V[75]); 23 cout<<endl; 24 25 return 0; 26 }
5.note:別忘了加上相應的頭文件
廣度優先搜索是通過隊列這個數據結構來存儲每個頂點的,而文件操作也要加入相應的文件頭文件。
1 #include<iostream> 2 #include<fstream> 3 #include<queue>//引入隊列頭文件
上述代碼還有許多改進的地方,期待探討和指正。
於2017年4月8日編輯完成。
