圖的深度優先遍歷(DFS)和廣度優先遍歷(BFS)


概述

圖的遍歷是指從圖中的任一頂點出發,對圖中的所有頂點訪問一次且只訪問一次。圖的遍歷操作和樹的遍歷操作功能相似。圖的遍歷是圖的一種基本操作,圖的其它算法如求解圖的連通性問題,拓撲排序,求關鍵路徑等都是建立在遍歷算法的基礎之上。

由於圖結構本身的複雜性,所以圖的遍歷操作也較複雜,主要表現在以下四個方面:
① 在圖結構中,沒有一個“自然”的首結點,圖中任意一個頂點都可作爲第一個被訪問的結點。
② 在非連通圖中,從一個頂點出發,只能夠訪問它所在的連通分量上的所有頂點,因此,還需考慮如何選取下一個出發點以訪問圖中其餘的連通分量。
③ 在圖結構中,如果有迴路存在,那麼一個頂點被訪問之後,有可能沿迴路又回到該頂點。

④ 在圖結構中,一個頂點可以和其它多個頂點相連,當這樣的頂點訪問過後,存在如何選取下一個要訪問的頂點的問題。

圖的遍歷通常有深度優先搜索和廣度優先搜索兩種方式,他們對無向圖和有向圖都適用。

1.深度優先搜索

深度優先搜索(Depth_Fisrst Search)遍歷類似於樹的先根遍歷,是樹的先根遍歷的推廣。

 假設初始狀態是圖中所有頂點未曾被訪問,則深度優先搜索可從圖中某個頂點發v 出發,訪問此頂點,然後依次從v 的未被訪問的鄰接點出發深度優先遍歷圖,直至圖中所有和v 有路徑相通的頂點都被訪問到;若此時圖中尚有頂點未被訪問,則另選圖中一個未曾被訪問的頂點作起始點,重複上述過程,直至圖中所有頂點都被訪問到爲止。

以如下圖的無向圖G5爲例,進行圖的深度優先搜索:


G5

搜索過程:



假設從頂點v1 出發進行搜索,在訪問了頂點v1 之後,選擇鄰接點v2。因爲v2 未曾訪問,則從v2 出發進行搜索。依次類推,接着從v4 、v8 、v5 出發進行搜索。在訪問了v5 之後,由於v5 的鄰接點都已被訪問,則搜索回到v8。由於同樣的理由,搜索繼續回到v4,v2 直至v1,此時由於v1 的另一個鄰接點未被訪問,則搜索又從v1 到v3,再繼續進行下去由此,得到的頂點訪問序列爲:



顯然,這是一個遞歸的過程。爲了在遍歷過程中便於區分頂點是否已被訪問,需附設訪問標誌數組visited[0:n-1], ,其初值爲FALSE ,一旦某個頂點被訪問,則其相應的分量置爲TRUE。
1)鄰接矩陣的存儲方式實現:

  1. // stdafx.h : include file for standard system include files,  
  2. // or project specific include files that are used frequently, but  
  3. // are changed infrequently  
  4. //  
  5.   
  6. #pragma once  
  7.   
  8. #include “targetver.h”  
  9. #include <stdio.h>    
  10. #include “stdlib.h”  
  11. #include <iostream>  
  12. using namespace std;  
  13.   
  14. //宏定義      
  15. #define TRUE   1      
  16. #define FALSE   0     
  17. #define NULL 0  
  18. #define OK    1      
  19. #define ERROR   0    
  20. #define INFEASIBLE -1      
  21. #define OVERFLOW -2    
  22.   
  23. #define INFINITY   INT_MAX  
  24. #define MAX_VERTEX_NUM 30  
  25.   
  26.   
  27. typedef int Status   ;  
  28. typedef int ElemType ;  
  29. typedef int VrType  ;  
  30. typedef char VertexType  ;  
  31. /**************************************************************/  
  32. / 數組表示:鄰接矩陣數據結構 
  33. /  
  34. /**************************************************************/  
  35.   
  36. typedef struct ArcCell{  
  37.     VrType adj;                         //頂點關係類型,對無權圖,0/1表示是否相鄰,有權圖表示權值  
  38.     ArcCell  *info;                     //弧相關信息的指針  
  39. }ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];  
  40.   
  41. typedef struct{  

    VertexType vexs[MAX_VERTEX_NUM];   //頂點向量  

  •     AdjMatrix arcs;                    //鄰接矩陣  
  •     int vexnum,arcnum;                 //圖的當前頂點數和弧數  
  • }MGraph;  
  • // stdafx.h : include file for standard system include files, 
    // or project specific include files that are used frequently, but
    // are changed infrequently
    //

    #pragma once #include "targetver.h" #include <stdio.h> #include "stdlib.h" #include <iostream> using namespace std; //宏定義 #define TRUE 1 #define FALSE 0 #define NULL 0 #define OK 1 #define ERROR 0 #define INFEASIBLE -1 #define OVERFLOW -2 #define INFINITY INT_MAX #define MAX_VERTEX_NUM 30 typedef int Status ; typedef int ElemType ; typedef int VrType ; typedef char VertexType ; /************************************************************************/ /* 數組表示:鄰接矩陣數據結構 */ /************************************************************************/ typedef struct ArcCell{ VrType adj; //頂點關係類型,對無權圖,0/1表示是否相鄰,有權圖表示權值 ArcCell *info; //弧相關信息的指針 }ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; typedef struct{ VertexType vexs[MAX_VERTEX_NUM]; //頂點向量 AdjMatrix arcs; //鄰接矩陣 int vexnum,arcnum; //圖的當前頂點數和弧數 }MGraph;

    1. // Test.cpp : Defines the entry point for the console application.    
    2. //    
    3. #include “stdafx.h”   
    4.   
    5. bool visited[MAX_VERTEX_NUM];  //訪問標識  
    6. Status (*VisitFunc) (int v);   //函數變量  
    7. /************************************************************************/  
    8. /*   
    9.     確定頂點v在圖G的位置 
    10. */  
    11. /************************************************************************/  
    12. int LocateVex(MGraph G,VertexType v)  
    13. {  
    14.     for(int i = 0; i<G.vexnum; ++i) {  
    15.         if(G.vexs[i] == v) return i;//找到  
    16.     }  
    17.     return -1;//不存在  
    18. }  
    19.   
    20. /************************************************************************/  
    21. /*   
    22.    
    23. */  
    24. /************************************************************************/  
    25. int FirstAdjVex(MGraph G,int v)  
    26. {  
    27.     int i ;  
    28.     for(i = 0; i<G.vexnum; i++)  
    29.         if( G.arcs[v][i].adj ) return i;  
    30.     if(i == (G.vexnum  -1)) return -1;  
    31.     return -1;   
    32.   
    33. }  
    34.   
    35. int NextAdjVex(MGraph G,int v,int w)  
    36. {  
    37.     int i;  
    38.     for( i = w+1; i<G.vexnum; i++)//+1  
    39.         if(G.arcs[v][i].adj) return i;  
    40.     if(i == (G.vexnum  -1)) return -1;  
    41.     return -1;  
    42.   
    43. }  
    44. /************************************************************************/  
    45. /* 
    46.  鄰接矩陣的無向圖的創建: 
    47.  註釋的代碼可以動態生成圖。 
    48. */  
    49. /************************************************************************/  
    50.   
    51. void CreatUDG(MGraph &G){  
    52.     cout<<”創建鄰接矩陣的無向圖:”<<endl;  
    53.     int i,j,k,w;  
    54.     //G5的存儲:  
    55.     G.arcnum = 8;  
    56.     G.vexnum = 9;  
    57.     for(i=0;i<G.vexnum;++i)  
    58.         for(j=0;j<G.vexnum;++j) {  
    59.             G.arcs[i][j].adj=0;  
    60.             G.arcs[i][j].info=NULL;  
    61.         }  
    62.     G.vexs[0] = ’1’;  
    63.     G.vexs[1] = ’2’;  
    64.     G.vexs[2] = ’3’;  
    65.     G.vexs[3] = ’4’;  
    66.     G.vexs[4] = ’5’;  
    67.     G.vexs[5] = ’6’;  
    68.     G.vexs[6] = ’7’;  
    69.     G.vexs[7] = ’8’;  
    70.   
    71.     G.arcs[0][1].adj = 1;  
    72.     G.arcs[0][1].info = NULL;  
    73.     G.arcs[1][0].adj = 1;  
    74.     G.arcs[1][0].info = NULL;  
    75.   
    76.     G.arcs[1][3].adj = 1;  
    77.     G.arcs[1][3].info = NULL;  
    78.     G.arcs[3][1].adj = 1;  
    79.     G.arcs[3][1].info = NULL;  
    80.   
    81.     G.arcs[3][7].adj = 1;  
    82.     G.arcs[3][7].info = NULL;  
    83.     G.arcs[7][3].adj = 1;  
    84.     G.arcs[7][3].info = NULL;  
    85.   
    86.     G.arcs[7][4].adj = 1;  
    87.     G.arcs[7][4].info = NULL;  
    88.     G.arcs[4][7].adj = 1;  
    89.     G.arcs[4][7].info = NULL;  
    90.   
    91.     G.arcs[4][1].adj = 1;  
    92.     G.arcs[4][1].info = NULL;  
    93.     G.arcs[1][4].adj = 1;  
    94.     G.arcs[1][4].info = NULL;  
    95.   
    96.     G.arcs[0][2].adj = 1;  
    97.     G.arcs[0][2].info = NULL;  
    98.     G.arcs[2][0].adj = 1;  
    99.     G.arcs[2][0].info = NULL;  
    100.   
    101.     G.arcs[2][5].adj = 1;  
    102.     G.arcs[2][5].info = NULL;  
    103.     G.arcs[5][2].adj = 1;  
    104.     G.arcs[5][2].info = NULL;  
    105.   
    106.     G.arcs[5][6].adj = 1;  
    107.     G.arcs[5][6].info = NULL;  
    108.     G.arcs[6][5].adj = 1;  
    109.     G.arcs[6][5].info = NULL;  
    110.   
    111.     G.arcs[6][2].adj = 1;  
    112.     G.arcs[6][2].info = NULL;  
    113.     G.arcs[2][6].adj = 1;  
    114.     G.arcs[2][6].info = NULL;  
    115.     return ;  
    116.     /* 
    117.     char v1,v2; 
    118.     cout<<”請輸入無向圖頂點個數和邊數:”<<endl; 
    119.     cin>>G.vexnum>>G.arcnum; 
    120.     cout<<”請輸入”<<G.vexnum<<”個頂點的值:”<<endl; 
    121.     for(i=0;i<G.vexnum;++i) cin>>G.vexs[i]; 
    122.     for(i=0;i<G.vexnum;++i) 
    123.         for(j=0;j<G.vexnum;++j) { 
    124.             G.arcs[i][j].adj=0; 
    125.             G.arcs[i][j].info=NULL; 
    126.         } 
    127.  
    128.         for( k=1;k<=G.arcnum;++k){ 
    129.             cout<<”請輸入第”<<k<<”條邊的兩個頂點值和它們的權重:”<<endl; 
    130.             cin>>v1>>v2>>w; 
    131.             i = LocateVex(G,v1);   j=LocateVex(G,v2);  
    132.             G.arcs[i][j].adj=w; 
    133.             G.arcs[j][i]=G.arcs[i][j]; 
    134.         } 
    135.         */  
    136. }  
    137. /************************************************************************/  
    138. /* 有向圖鄰接矩陣的創建 
    139. */  
    140. /************************************************************************/  
    141. void CreatDG(MGraph &G){  
    142.     int i,j,k,w;  
    143.     char v1,v2;  
    144.     G.arcnum = 8;  
    145.     G.vexnum = 9;  
    146.     cout<<”請輸入有向圖頂點個數和邊數:”;  
    147.     cin>> G.vexnum>> G.arcnum;  
    148.     cout<<”請輸入”<<G.vexnum<<“個頂點的值:”<<endl;  
    149.     for(i=0;i<G.vexnum;++i) cin>>G.vexs[i];  
    150.     for(i=0;i<G.vexnum;++i)  
    151.         for(j=0;j<G.vexnum;++j) {  
    152.             G.arcs[i][j].adj = 0;  
    153.             G.arcs[i][j].info = NULL;  
    154.         }  
    155.         for( k=1;k<=G.arcnum;++k){  
    156.             cout<<”請輸入第”<<k<<“條邊的兩個頂點值和它們的權重:”<<endl;  
    157.             cin>>v1>>v2>>w;  
    158.             i= LocateVex(G,v1);   j = LocateVex(G,v2);   
    159.             G.arcs[i][j].adj = w;  
    160.         }  
    161. }  
    162.   
    163.   
    164. void visitVex(MGraph G, int v){  
    165.     cout<<G.vexs[v]<<” ”;  
    166. }  
    167.   
    168. /************************************************************************/  
    169. /*  以V爲出發點對圖G 進行遞歸地DFS 搜索 
    170. */  
    171. /************************************************************************/  
    172. void DFS(MGraph G,int v){  
    173.     visited[v] = true;  
    174.     visitVex( G,  v); //訪問第v 個頂點  
    175.     for(int w = FirstAdjVex(G,v); w>=0; w = NextAdjVex(G,v,w)){  
    176.         if(!visited[w]) DFS(G,w); //w未訪問過,遞歸DFS搜索  
    177.   
    178.     }  
    179. }  
    180.   
    181. /************************************************************************/  
    182. /*      
    183. 無向圖的深度遍歷        
    184. */  
    185. /************************************************************************/  
    186. void DFSTraverse(MGraph G){//  
    187.     int v;  
    188.     for( v = 0; v < G.vexnum; ++v) visited[v] = false;  
    189.     for( v = 0; v < G.vexnum; )   
    190.         if(!visited[v]) DFS( G, v); //v未訪問過,從vi開始DFS搜索  
    191.         ++v;//不要像書上寫的那樣,++v放到for語句,這樣會導致多出一次訪問  
    192.   
    193. }  
    194.   
    195.   
    196. void printMGraph(MGraph G){  
    197.     cout<<”鄰接矩陣已經創建,鄰接矩陣爲:”<<endl;  
    198.     for(int i=0;i<G.vexnum;i++){  
    199.         for(int j=0;j<G.vexnum;j++)  
    200.             cout<<G.arcs[i][j].adj<<” ”;  
    201.         cout<<endl;  
    202.     }  
    203. }  
    204.   
    205.   
    206. void main(){  
    207.       
    208.     MGraph G;  
    209.   
    210.     CreatUDG(G);  
    211.     printMGraph(G);  
    212.     cout<<”無向圖鄰接矩陣的深度遍歷結果:”<<endl;  
    213.     DFSTraverse(G);  
    214. }  
    // Test.cpp : Defines the entry point for the console application.  
    //  
    
    
    
    
    
    #include "stdafx.h" bool visited[MAX_VERTEX_NUM]; //訪問標識 Status (*VisitFunc) (int v); //函數變量 /************************************************************************/ /* 確定頂點v在圖G的位置 */ /************************************************************************/ int LocateVex(MGraph G,VertexType v) { for(int i = 0; i<G.vexnum; ++i) { if(G.vexs[i] == v) return i;//找到 } return -1;//不存在 } /************************************************************************/ /* */ /************************************************************************/ int FirstAdjVex(MGraph G,int v) { int i ; for(i = 0; i<G.vexnum; i++) if( G.arcs[v][i].adj ) return i; if(i == (G.vexnum -1)) return -1; return -1; } int NextAdjVex(MGraph G,int v,int w) { int i; for( i = w+1; i<G.vexnum; i++)//+1 if(G.arcs[v][i].adj) return i; if(i == (G.vexnum -1)) return -1; return -1; } /************************************************************************/ /* 鄰接矩陣的無向圖的創建: 註釋的代碼可以動態生成圖。 */ /************************************************************************/ void CreatUDG(MGraph &G){ cout<<"創建鄰接矩陣的無向圖:"<<endl; int i,j,k,w; //G5的存儲: G.arcnum = 8; G.vexnum = 9; for(i=0;i<G.vexnum;++i) for(j=0;j<G.vexnum;++j) { G.arcs[i][j].adj=0; G.arcs[i][j].info=NULL; } G.vexs[0] = '1'; G.vexs[1] = '2'; G.vexs[2] = '3'; G.vexs[3] = '4'; G.vexs[4] = '5'; G.vexs[5] = '6'; G.vexs[6] = '7'; G.vexs[7] = '8'; G.arcs[0][1].adj = 1; G.arcs[0][1].info = NULL; G.arcs[1][0].adj = 1; G.arcs[1][0].info = NULL; G.arcs[1][3].adj = 1; G.arcs[1][3].info = NULL; G.arcs[3][1].adj = 1; G.arcs[3][1].info = NULL; G.arcs[3][7].adj = 1; G.arcs[3][7].info = NULL; G.arcs[7][3].adj = 1; G.arcs[7][3].info = NULL; G.arcs[7][4].adj = 1; G.arcs[7][4].info = NULL; G.arcs[4][7].adj = 1; G.arcs[4][7].info = NULL; G.arcs[4][1].adj = 1; G.arcs[4][1].info = NULL; G.arcs[1][4].adj = 1; G.arcs[1][4].info = NULL; G.arcs[0][2].adj = 1; G.arcs[0][2].info = NULL; G.arcs[2][0].adj = 1; G.arcs[2][0].info = NULL; G.arcs[2][5].adj = 1; G.arcs[2][5].info = NULL; G.arcs[5][2].adj = 1; G.arcs[5][2].info = NULL; G.arcs[5][6].adj = 1; G.arcs[5][6].info = NULL; G.arcs[6][5].adj = 1; G.arcs[6][5].info = NULL; G.arcs[6][2].adj = 1; G.arcs[6][2].info = NULL; G.arcs[2][6].adj = 1; G.arcs[2][6].info = NULL; return ; /* char v1,v2; cout<<"請輸入無向圖頂點個數和邊數:"<<endl; cin>>G.vexnum>>G.arcnum; cout<<"請輸入"<<G.vexnum<<"個頂點的值:"<<endl; for(i=0;i<G.vexnum;++i) cin>>G.vexs[i]; for(i=0;i<G.vexnum;++i) for(j=0;j<G.vexnum;++j) { G.arcs[i][j].adj=0; G.arcs[i][j].info=NULL; } for( k=1;k<=G.arcnum;++k){ cout<<"請輸入第"<<k<<"條邊的兩個頂點值和它們的權重:"<<endl; cin>>v1>>v2>>w; i = LocateVex(G,v1); j=LocateVex(G,v2); G.arcs[i][j].adj=w; G.arcs[j][i]=G.arcs[i][j]; } */ } /************************************************************************/ /* 有向圖鄰接矩陣的創建 */ /************************************************************************/ void CreatDG(MGraph &G){ int i,j,k,w; char v1,v2; G.arcnum = 8; G.vexnum = 9; cout<<"請輸入有向圖頂點個數和邊數:"; cin>> G.vexnum>> G.arcnum; cout<<"請輸入"<<G.vexnum<<"個頂點的值:"<<endl; for(i=0;i<G.vexnum;++i) cin>>G.vexs[i]; for(i=0;i<G.vexnum;++i) for(j=0;j<G.vexnum;++j) { G.arcs[i][j].adj = 0; G.arcs[i][j].info = NULL; } for( k=1;k<=G.arcnum;++k){ cout<<"請輸入第"<<k<<"條邊的兩個頂點值和它們的權重:"<<endl; cin>>v1>>v2>>w; i= LocateVex(G,v1); j = LocateVex(G,v2); G.arcs[i][j].adj = w; } } void visitVex(MGraph G, int v){ cout<<G.vexs[v]<<" "; } /************************************************************************/ /* 以V爲出發點對圖G 進行遞歸地DFS 搜索 */ /************************************************************************/ void DFS(MGraph G,int v){ visited[v] = true; visitVex( G, v); //訪問第v 個頂點 for(int w = FirstAdjVex(G,v); w>=0; w = NextAdjVex(G,v,w)){ if(!visited[w]) DFS(G,w); //w未訪問過,遞歸DFS搜索 } } /************************************************************************/ /* 無向圖的深度遍歷 */ /************************************************************************/ void DFSTraverse(MGraph G){// int v; for( v = 0; v < G.vexnum; ++v) visited[v] = false; for( v = 0; v < G.vexnum; ) if(!visited[v]) DFS( G, v); //v未訪問過,從vi開始DFS搜索 ++v;//不要像書上寫的那樣,++v放到for語句,這樣會導致多出一次訪問 } void printMGraph(MGraph G){ cout<<"鄰接矩陣已經創建,鄰接矩陣爲:"<<endl; for(int i=0;i<G.vexnum;i++){ for(int j=0;j<G.vexnum;j++) cout<<G.arcs[i][j].adj<<" "; cout<<endl; } } void main(){ MGraph G; CreatUDG(G); printMGraph(G); cout<<"無向圖鄰接矩陣的深度遍歷結果:"<<endl; DFSTraverse(G); }
    2) 鄰接表的表示實現方式

    1. // stdafx.h : include file for standard system include files,  
    2. // or project specific include files that are used frequently, but  
    3. // are changed infrequently  
    4. //  
    5.   
    6. #pragma once  
    7.   
    8. #include “targetver.h”  
    9. #include <stdio.h>    
    10. #include “stdlib.h”  
    11. #include <iostream>  
    12. using namespace std;  
    13.   
    14. //宏定義      
    15. #define TRUE   1      
    16. #define FALSE   0     
    17. #define NULL 0  
    18. #define OK    1      
    19. #define ERROR   0    
    20. #define INFEASIBLE -1      
    21. #define OVERFLOW -2    
    22.   
    23. #define INFINITY   INT_MAX  
    24. #define MAX_VERTEX_NUM 30  
    25.   
    26.   
    27. typedef int Status   ;  
    28. typedef int ElemType ;  
    29. typedef int VrType  ;  
    30. typedef char VertexType  ;  
    31.   
    32. /************************************************************************/  
    33. /*  鄰接表示的圖數據結構 
    34. */  
    35. /************************************************************************/  
    36. //定義邊結點,即表節點  
    37. typedef struct ArcNode   
    38. {  
    39.     int adjvex;             //弧所指的頂點位置  
    40.     ArcNode *nextarc;       //指向下一條弧的指針  
    41. }ArcNode;  
    42.   
    43. //定義頂點節點,即頭節點  
    44. typedef struct VNode    
    45. {  
    46.     VertexType data;        //頂點信息  
    47.     ArcNode *firstarc;      //指向第一條依附該頂點的弧的指針  
    48. }VNode,AdjList[MAX_VERTEX_NUM];  
    49.   
    50. //定義無向圖     
    51. typedef struct                        
    52. {  
    53.     AdjList vertices;  
    54.     int vexnum,arcnum;   //圖的當前頂點數和弧數  
    55. }ALGraph;  
    // stdafx.h : include file for standard system include files,
    // or project specific include files that are used frequently, but
    // are changed infrequently
    //
    
    
    
    
    
    
    #pragma once #include "targetver.h" #include <stdio.h> #include "stdlib.h" #include <iostream> using namespace std; //宏定義 #define TRUE 1 #define FALSE 0 #define NULL 0 #define OK 1 #define ERROR 0 #define INFEASIBLE -1 #define OVERFLOW -2 #define INFINITY INT_MAX #define MAX_VERTEX_NUM 30 typedef int Status ; typedef int ElemType ; typedef int VrType ; typedef char VertexType ; /************************************************************************/ /* 鄰接表示的圖數據結構 */ /************************************************************************/ //定義邊結點,即表節點 typedef struct ArcNode { int adjvex; //弧所指的頂點位置 ArcNode *nextarc; //指向下一條弧的指針 }ArcNode; //定義頂點節點,即頭節點 typedef struct VNode { VertexType data; //頂點信息 ArcNode *firstarc; //指向第一條依附該頂點的弧的指針 }VNode,AdjList[MAX_VERTEX_NUM]; //定義無向圖 typedef struct { AdjList vertices; int vexnum,arcnum; //圖的當前頂點數和弧數 }ALGraph;
    1. // Test.cpp : Defines the entry point for the console application.    
    2. //    
    3. #include “stdafx.h”   
    4.   
    5. bool visited[MAX_VERTEX_NUM];  //訪問標識  
    6. Status (*VisitFunc) (int v);   //函數變量  
    7.   
    8.   
    9. /************************************************************************/  
    10. /* 在無向圖中添加以m,n爲頂點的邊 
    11. */  
    12. /************************************************************************/  
    13. void ArcAdd(ALGraph &G,int m,int n){  
    14.   
    15.     ArcNode *p,*h,*q;  
    16.     p = new ArcNode;  
    17.     p->adjvex = m;  
    18.     p->nextarc = NULL;  
    19.     h = q = G.vertices[n].firstarc;  
    20.     if(q == NULL)  
    21.         G.vertices[n].firstarc = p;  
    22.     else {   
    23.         if((p->adjvex)>(q->adjvex)){   
    24.             p->nextarc = q;  
    25.             G.vertices[n].firstarc = p;  
    26.         }  
    27.         else {   
    28.             while( G.vertices[n].firstarc != NULL && q->nextarc != NULL && (p->adjvex)<(q->adjvex)){ //使鄰接表中邊的數據按大到小排列。    
    29.                 h = q;  
    30.                 q = q->nextarc;  
    31.             }  
    32.             if(q->nextarc == NULL&&(p->adjvex)<(q->adjvex)){    
    33.                 q->nextarc = p;  
    34.             }  
    35.             else {    
    36.                 p->nextarc = q;  
    37.                 h->nextarc = p;  
    38.             }  
    39.         }  
    40.     }  
    41. }  
    42. /************************************************************************/  
    43. /* 
    44. 創建無向圖 
    45. */  
    46. /************************************************************************/  
    47. void CreateDG(ALGraph &G){    
    48.     cout<<”請輸入頂點個數和邊數:”<<endl;  
    49.     cin>> G.vexnum>> G.arcnum;  
    50.     cout<<”請輸入頂點值:”<<endl;  
    51.     for(int i= 1; i<= G.vexnum; i++) {  
    52.         char t;  
    53.         cin>>t;  
    54.         G.vertices[i].data = t;  
    55.         G.vertices[i].firstarc = NULL;  
    56.     }  
    57.     int m, n;  
    58.     for(int k = 1; k<=G.arcnum; k++){  
    59.         cout<<”請輸入第”<<k<<“條邊的兩個頂點:”<<endl;  
    60.         cin>>m>>n;  
    61.         if(m<= G.vexnum && n <= G.vexnum && m>0 && n>0){  
    62.             ArcAdd(G, m, n);  
    63.             ArcAdd(G, n, m);  
    64.         }  
    65.         else  cout<<“ERROR.”<<endl;   
    66.     }  
    67. }  
    68. /************************************************************************/  
    69. /* 打印鄰接表的無向圖       
    70. */  
    71. /************************************************************************/  
    72. void PrintGraph(ALGraph G)    
    73. {  
    74.     cout<<”無向圖的創建完成,該圖的鄰接表表示爲:”<<endl;  
    75.     ArcNode *p;  
    76.     for(int i=1; i<=G.vexnum; i++)  
    77.     {  
    78.         if(G.vertices[i].firstarc == NULL)  
    79.             cout<<i<<G.vertices[i].data<<”–>NULL”<<endl;  
    80.         else   
    81.         {  
    82.             p = G.vertices[i].firstarc;  
    83.             cout<<i<<G.vertices[i].data<<”–>”;  
    84.             while(p->nextarc!=NULL)  
    85.             {  
    86.                 cout<<p->adjvex<<”–>”;  
    87.                 p = p->nextarc;  
    88.             }  
    89.             cout<<p->adjvex<<”–>NULL”<<endl;  
    90.         }  
    91.     }  
    92. }  
    93.   
    94.   
    95. /************************************************************************/  
    96. /*     返回v的第一個鄰接頂點。若頂點在G中沒有鄰接表頂點,則返回“空”。    
    97. */  
    98. /************************************************************************/  
    99. int FirstAdjVex(ALGraph G,int v)  
    100. {   
    101.     if(G.vertices[v].firstarc)  
    102.         return G.vertices[v].firstarc->adjvex;  
    103.     else  
    104.         return NULL;  
    105. }  
    106. /************************************************************************/  
    107. /*    
    108.   返回v的(相對於w的)下一個鄰接頂點。若w是v的最後一個鄰接點,則返回“回”。 
    109. */  
    110. /************************************************************************/  
    111. int NextAdjVex(ALGraph G,int v,int w)     
    112. {  
    113.     ArcNode *p;  
    114.     if(G.vertices[v].firstarc==NULL)  
    115.         return NULL;  
    116.     else {  
    117.         p = G.vertices[v].firstarc;  
    118.         while(p->adjvex!=w) p = p->nextarc;  
    119.   
    120.         if(p->nextarc == NULL) return NULL;  
    121.         else  return p->nextarc->adjvex;  
    122.     }  
    123. }  
    124.   
    125.   
    126.   
    127. void visitVex(ALGraph G, int v){  
    128.     cout<<G.vertices[v].data<<” ”;  
    129. }  
    130.   
    131. /************************************************************************/  
    132. /*      
    133. 無向圖的深度遍歷        
    134. */  
    135. /************************************************************************/  
    136. //從第v個頂點出發遞歸地深度優先遍歷圖G  
    137. void DFS(ALGraph G,int v)  
    138. {  
    139.     visited[v] = true;  
    140.     visitVex(G, v);  
    141.     for(int w = FirstAdjVex(G,v);w >= 1; w = NextAdjVex(G,v,w))  
    142.         if(!visited[w]) DFS(G,w);  
    143. }  
    144. //對圖G作深度優先遍歷  
    145. void DFSTraverse(ALGraph G)  
    146. {   
    147.     for(int v = 1; v <= G.vexnum; v++) visited[v]=false;  
    148.     for(int m = 1; m <= G.vexnum; m++)  
    149.         if(!visited[m]) DFS(G,m);  
    150. }  
    151.   
    152. void main(){  
    153.     ALGraph G;  
    154.     CreateDG(G);  
    155.     PrintGraph(G);  
    156.     DFSTraverse(G);  
    157. }  
    // Test.cpp : Defines the entry point for the console application.  
    //  
    
    
    
    
    
    #include "stdafx.h" bool visited[MAX_VERTEX_NUM]; //訪問標識 Status (*VisitFunc) (int v); //函數變量 /************************************************************************/ /* 在無向圖中添加以m,n爲頂點的邊 */ /************************************************************************/ void ArcAdd(ALGraph &G,int m,int n){ ArcNode *p,*h,*q; p = new ArcNode; p->adjvex = m; p->nextarc = NULL; h = q = G.vertices[n].firstarc; if(q == NULL) G.vertices[n].firstarc = p; else { if((p->adjvex)>(q->adjvex)){ p->nextarc = q; G.vertices[n].firstarc = p; } else { while( G.vertices[n].firstarc != NULL && q->nextarc != NULL && (p->adjvex)<(q->adjvex)){ //使鄰接表中邊的數據按大到小排列。 h = q; q = q->nextarc; } if(q->nextarc == NULL&&(p->adjvex)<(q->adjvex)){ q->nextarc = p; } else { p->nextarc = q; h->nextarc = p; } } } } /************************************************************************/ /* 創建無向圖 */ /************************************************************************/ void CreateDG(ALGraph &G){ cout<<"請輸入頂點個數和邊數:"<<endl; cin>> G.vexnum>> G.arcnum; cout<<"請輸入頂點值:"<<endl; for(int i= 1; i<= G.vexnum; i++) { char t; cin>>t; G.vertices[i].data = t; G.vertices[i].firstarc = NULL; } int m, n; for(int k = 1; k<=G.arcnum; k++){ cout<<"請輸入第"<<k<<"條邊的兩個頂點:"<<endl; cin>>m>>n; if(m<= G.vexnum && n <= G.vexnum && m>0 && n>0){ ArcAdd(G, m, n); ArcAdd(G, n, m); } else cout<<"ERROR."<<endl; } } /************************************************************************/ /* 打印鄰接表的無向圖 */ /************************************************************************/ void PrintGraph(ALGraph G) { cout<<"無向圖的創建完成,該圖的鄰接表表示爲:"<<endl; ArcNode *p; for(int i=1; i<=G.vexnum; i++) { if(G.vertices[i].firstarc == NULL) cout<<i<<G.vertices[i].data<<"-->NULL"<<endl; else { p = G.vertices[i].firstarc; cout<<i<<G.vertices[i].data<<"-->"; while(p->nextarc!=NULL) { cout<<p->adjvex<<"-->"; p = p->nextarc; } cout<<p->adjvex<<"-->NULL"<<endl; } } } /************************************************************************/ /* 返回v的第一個鄰接頂點。若頂點在G中沒有鄰接表頂點,則返回“空”。 */ /************************************************************************/ int FirstAdjVex(ALGraph G,int v) { if(G.vertices[v].firstarc) return G.vertices[v].firstarc->adjvex; else return NULL; } /************************************************************************/ /* 返回v的(相對於w的)下一個鄰接頂點。若w是v的最後一個鄰接點,則返回“回”。 */ /************************************************************************/ int NextAdjVex(ALGraph G,int v,int w) { ArcNode *p; if(G.vertices[v].firstarc==NULL) return NULL; else { p = G.vertices[v].firstarc; while(p->adjvex!=w) p = p->nextarc; if(p->nextarc == NULL) return NULL; else return p->nextarc->adjvex; } } void visitVex(ALGraph G, int v){ cout<<G.vertices[v].data<<" "; } /************************************************************************/ /* 無向圖的深度遍歷 */ /************************************************************************/ //從第v個頂點出發遞歸地深度優先遍歷圖G void DFS(ALGraph G,int v) { visited[v] = true; visitVex(G, v); for(int w = FirstAdjVex(G,v);w >= 1; w = NextAdjVex(G,v,w)) if(!visited[w]) DFS(G,w); } //對圖G作深度優先遍歷 void DFSTraverse(ALGraph G) { for(int v = 1; v <= G.vexnum; v++) visited[v]=false; for(int m = 1; m <= G.vexnum; m++) if(!visited[m]) DFS(G,m); } void main(){ ALGraph G; CreateDG(G); PrintGraph(G); DFSTraverse(G); }


    分析上述算法,在遍歷時,對圖中每個頂點至多調用一次DFS 函數,因爲一旦某個頂點被標誌成已被訪問,就不再從它出發進行搜索。因此,遍歷圖的過程實質上是對每個頂點查找其鄰接點的過程。其耗費的時間則取決於所採用的存儲結構。當用二維數組表示鄰接矩陣圖的存儲結構時,查找每個頂點的鄰接點所需時間爲O(n2) ,其中n 爲圖中頂點數。而當以鄰接表作圖的存儲結構時,找鄰接點所需時間爲O(e),其中e 爲無向圖中邊的數或有向圖中弧的數。由此,當以鄰接表作存儲結構時,深度優先搜索遍歷圖的時間複雜度爲O(n+e) 。


    2.廣度優先搜索

    廣度優先搜索(Breadth_First Search) 遍歷類似於樹的按層次遍歷的過程。

    假設從圖中某頂點v 出發,在訪問了v 之後依次訪問v 的各個未曾訪問過和鄰接點,然後分別從這些鄰接點出發依次訪問它們的鄰接點,並使“先被訪問的頂點的鄰接點”先於“後被訪問的頂點的鄰接點”被訪問,直至圖中所有已被訪問的頂點的鄰接點都被訪問到。若此時圖中尚有頂點未被訪問,則另選圖中一個未曾被訪問的頂點作起始點,重複上述過程,直至圖中所有頂點都被訪問到爲止。換句話說,廣度優先搜索遍歷圖的過程中以v 爲起始點,由近至遠,依次訪問和v 有路徑相通且路徑長度爲1,2,…的頂點。

    對圖如下圖所示無向圖G5 進行廣度優先搜索遍歷:



    廣度搜索過程:


    首先訪問v1 和v1 的鄰接點v2 和v3,然後依次訪問v2 的鄰接點v4 和v5 及v3 的鄰接點v6 和v7,最後訪問v4 的鄰接點v8。由於這些頂點的鄰接點均已被訪問,並且圖中所有頂點都被訪問,由些完成了圖的遍歷。得到的頂點訪問序列爲:


    v1→v2 →v3 →v4→ v5→ v6→ v7 →v8

    和深度優先搜索類似,在遍歷的過程中也需要一個訪問標誌數組。並且,爲了順次訪問路徑長度爲2、3、…的頂點,需附設隊列以存儲已被訪問的路徑長度爲1、2、… 的頂點。

    實現:

    1. // stdafx.h : include file for standard system include files,  
    2. // or project specific include files that are used frequently, but  
    3. // are changed infrequently  
    4. //  
    5.   
    6. #pragma once  
    7.   
    8. #include <stdio.h>    
    9. #include “stdlib.h”  
    // stdafx.h : include file for standard system include files,
    // or project specific include files that are used frequently, but
    // are changed infrequently
    //
    
    
    
    
    
    
    #pragma once #include <stdio.h> #include "stdlib.h"
    1. // func.h :  
    2. #pragma once  
    3.   
    4. #include <iostream>  
    5. using namespace std;  
    6.   
    7. //宏定義      
    8. #define TRUE   1      
    9. #define FALSE   0     
    10. #define NULL 0  
    11. #define OK    1      
    12. #define ERROR   0    
    13. #define INFEASIBLE -1      
    14. #define OVERFLOW -2    
    15.   
    16. #define INFINITY   INT_MAX  
    17. #define MAX_VERTEX_NUM 30  
    18.   
    19.   
    20. typedef int Status   ;  
    21. typedef int ElemType ;  
    22. typedef int VrType  ;  
    23. typedef char VertexType  ;  
    24.   
    25. /************************************************************************/  
    26. /*  鄰接表示的圖數據結構 
    27. */  
    28. /************************************************************************/  
    29. //定義邊結點  
    30. typedef struct ArcNode   
    31. {  
    32.     int adjvex;             //弧所指的頂點位置  
    33.     ArcNode *nextarc;       //指向下一條弧的指針  
    34. }ArcNode;  
    35.   
    36. //定義頂點結點  
    37. typedef struct VNode    
    38. {  
    39.     VertexType data;        //頂點信息  
    40.     ArcNode *firstarc;      //指向第一條依附該頂點的弧的指針  
    41. }VNode,AdjList[MAX_VERTEX_NUM];  
    42.   
    43. //定義無向圖     
    44. typedef struct                        
    45. {  
    46.     AdjList vertices;  
    47.     int vexnum,arcnum;   //圖的當前頂點數和弧數  
    48. }ALGraph;  
    49.   
    50.   
    51. /************************************************************************/  
    52. /* 需要                                                                     */  
    53. /************************************************************************/  
    54. typedef struct node //定義結點  
    55. {  
    56.     char data;  
    57.     node *next;  
    58. }*Link;  
    59.   
    60. typedef struct //定義鏈表  
    61. {  
    62.     Link head,tail;  
    63.     int len;  
    64. }Queue;  
    65.   
    66. /************************************************************************/  
    67. /* 構造一個帶頭結點和尾結點的空的線性鏈表隊列Q 
    68. */  
    69. /************************************************************************/  
    70. Status InitQueue(Queue &Q)  
    71. {  
    72.     Q.head = new node;  
    73.     Q.head->next = Q.tail = new node;  
    74.     Q.tail->next = NULL;  
    75.     Q.len = 0;  
    76.     return 0;  
    77. }  
    78.   
    79. /************************************************************************/  
    80. /*  
    81.  //在線性鏈表的隊列L的結尾添加一個結點 
    82. */  
    83. /************************************************************************/  
    84.  void EnQueue(Queue &Q,int e)  
    85. {  
    86.     Link q = new node;  
    87.     Q.tail->next = q;  
    88.     Q.tail->data = e;  
    89.     Q.tail = q;  
    90.     Q.tail->next = NULL;  
    91.     Q.len++;  
    92. }  
    93. /************************************************************************/  
    94. /* 出列,並將出列的元素值用e返回 
    95. */  
    96. /************************************************************************/  
    97. void DeleteQueue(Queue &Q,int &e)  
    98. {  
    99.     if(Q.head->next == Q.tail) {  
    100.         cout<<”隊列爲空”<<endl;  
    101.         e = NULL;  
    102.     } else {  
    103.         Link p,q;  
    104.         p = Q.head->next;  
    105.         q = p->next;  
    106.         Q.head->next = q;  
    107.         e = p->data;  
    108.         delete p;  
    109.         Q.len–;  
    110.     }  
    111. }  
    // func.h :
    
    
    
    
    
    #pragma once #include <iostream> using namespace std; //宏定義 #define TRUE 1 #define FALSE 0 #define NULL 0 #define OK 1 #define ERROR 0 #define INFEASIBLE -1 #define OVERFLOW -2 #define INFINITY INT_MAX #define MAX_VERTEX_NUM 30 typedef int Status ; typedef int ElemType ; typedef int VrType ; typedef char VertexType ; /************************************************************************/ /* 鄰接表示的圖數據結構 */ /************************************************************************/ //定義邊結點 typedef struct ArcNode { int adjvex; //弧所指的頂點位置 ArcNode *nextarc; //指向下一條弧的指針 }ArcNode; //定義頂點結點 typedef struct VNode { VertexType data; //頂點信息 ArcNode *firstarc; //指向第一條依附該頂點的弧的指針 }VNode,AdjList[MAX_VERTEX_NUM]; //定義無向圖 typedef struct { AdjList vertices; int vexnum,arcnum; //圖的當前頂點數和弧數 }ALGraph; /************************************************************************/ /* 需要 */ /************************************************************************/ typedef struct node //定義結點 { char data; node *next; }*Link; typedef struct //定義鏈表 { Link head,tail; int len; }Queue; /************************************************************************/ /* 構造一個帶頭結點和尾結點的空的線性鏈表隊列Q */ /************************************************************************/ Status InitQueue(Queue &Q) { Q.head = new node; Q.head->next = Q.tail = new node; Q.tail->next = NULL; Q.len = 0; return 0; } /************************************************************************/ /* //在線性鏈表的隊列L的結尾添加一個結點 */ /************************************************************************/ void EnQueue(Queue &Q,int e) { Link q = new node; Q.tail->next = q; Q.tail->data = e; Q.tail = q; Q.tail->next = NULL; Q.len++; } /************************************************************************/ /* 出列,並將出列的元素值用e返回 */ /************************************************************************/ void DeleteQueue(Queue &Q,int &e) { if(Q.head->next == Q.tail) { cout<<"隊列爲空"<<endl; e = NULL; } else { Link p,q; p = Q.head->next; q = p->next; Q.head->next = q; e = p->data; delete p; Q.len--; } }
    1. // Test.cpp : Defines the entry point for the console application.    
    2. //    
    3. #include “stdafx.h”   
    4. #include “func.h”  
    5. bool visited[MAX_VERTEX_NUM];  //訪問標識  
    6. Status (*VisitFunc) (int v);   //函數變量  
    7.   
    8. /************************************************************************/  
    9. /* 在無向圖中添加以m,n爲頂點的邊 
    10. */  
    11. /************************************************************************/  
    12. void ArcAdd(ALGraph &G,int m,int n){  
    13.   
    14.     ArcNode *p,*h,*q;  
    15.     p = new ArcNode;  
    16.     p->adjvex = m;  
    17.     p->nextarc = NULL;  
    18.     h = q = G.vertices[n].firstarc;  
    19.     if(q == NULL)  
    20.         G.vertices[n].firstarc = p;  
    21.     else {   
    22.         if((p->adjvex)>(q->adjvex)){   
    23.             p->nextarc = q;  
    24.             G.vertices[n].firstarc = p;  
    25.         }  
    26.         else {   
    27.             while( G.vertices[n].firstarc != NULL && q->nextarc != NULL && (p->adjvex)<(q->adjvex)){   
    28.                 //使鄰接表中邊的數據按大到小排列。    
    29.                 h = q;  
    30.                 q = q->nextarc;  
    31.             }  
    32.             if(q->nextarc == NULL&&(p->adjvex)<(q->adjvex)){    
    33.                 q->nextarc = p;  
    34.             }  
    35.             else {    
    36.                 p->nextarc = q;  
    37.                 h->nextarc = p;  
    38.             }  
    39.         }  
    40.     }  
    41. }  
    42. /************************************************************************/  
    43. /* 
    44. 創建無向圖 
    45. */  
    46. /************************************************************************/  
    47. void CreateDG(ALGraph &G){    
    48.     cout<<”請輸入頂點個數和邊數:”<<endl;  
    49.     cin>> G.vexnum>> G.arcnum;  
    50.     cout<<”請輸入頂點值:”<<endl;  
    51.     for(int i= 1; i<= G.vexnum; i++) {  
    52.         char t;  
    53.         cin>>t;  
    54.         G.vertices[i].data = t;  
    55.         G.vertices[i].firstarc = NULL;  
    56.     }  
    57.     int m, n;  
    58.     for(int k = 1; k<=G.arcnum; k++){  
    59.         cout<<”請輸入第”<<k<<“條邊的兩個頂點:”<<endl;  
    60.         cin>>m>>n;  
    61.         if(m<= G.vexnum && n <= G.vexnum && m>0 && n>0){  
    62.             ArcAdd(G, m, n);  
    63.             ArcAdd(G, n, m);  
    64.         }  
    65.         else  cout<<“ERROR.”<<endl;   
    66.     }  
    67. }  
    68.   
    69. /************************************************************************/  
    70. /* 打印鄰接表的無向圖       
    71. */  
    72. /************************************************************************/  
    73. void PrintGraph(ALGraph G)    
    74. {  
    75.     cout<<”無向圖的創建完成,該圖的鄰接表表示爲:”<<endl;  
    76.     ArcNode *p;  
    77.     for(int i=1; i<=G.vexnum; i++)  
    78.     {  
    79.         if(G.vertices[i].firstarc == NULL)  
    80.             cout<<i<<G.vertices[i].data<<”–>NULL”<<endl;  
    81.         else   
    82.         {  
    83.             p = G.vertices[i].firstarc;  
    84.             cout<<i<<G.vertices[i].data<<”–>”;  
    85.             while(p->nextarc!=NULL)  
    86.             {  
    87.                 cout<<p->adjvex<<”–>”;  
    88.                 p = p->nextarc;  
    89.             }  
    90.             cout<<p->adjvex<<”–>NULL”<<endl;  
    91.         }  
    92.     }  
    93. }  
    94.   
    95. /************************************************************************/  
    96. /*     返回v的第一個鄰接頂點。若頂點在G中沒有鄰接表頂點,則返回“空”。    
    97. */  
    98. /************************************************************************/  
    99. int FirstAdjVex(ALGraph G,int v)  
    100. {   
    101.     if(G.vertices[v].firstarc)  
    102.         return G.vertices[v].firstarc->adjvex;  
    103.     else  
    104.         return NULL;  
    105. }  
    106. /************************************************************************/  
    107. /*    
    108.   返回v的(相對於w的)下一個鄰接頂點。若w是v的最後一個鄰接點,則返回“回”。 
    109. */  
    110. /************************************************************************/  
    111. int NextAdjVex(ALGraph G,int v,int w)     
    112. {  
    113.     ArcNode *p;  
    114.     if(G.vertices[v].firstarc==NULL)  
    115.         return NULL;  
    116.     else {  
    117.         p = G.vertices[v].firstarc;  
    118.         while(p->adjvex!=w) p = p->nextarc;  
    119.   
    120.         if(p->nextarc == NULL) return NULL;  
    121.         else  return p->nextarc->adjvex;  
    122.     }  
    123. }  
    124.   
    125. void visitVex(ALGraph G, int v){  
    126.     cout<<G.vertices[v].data<<” ”;  
    127. }  
    128.   
    129. /************************************************************************/  
    130. /*      
    131. 廣度優先遍歷圖G 
    132. */  
    133. /************************************************************************/  
    134.   
    135. void BFSTraverse(ALGraph G)  
    136. {  
    137.     Queue Q;  
    138.     int u;  
    139.     for(int m=1; m<= G.vexnum; m++) visited[m] = false;  
    140.     InitQueue(Q);//藉助輔助隊列。  
    141.     for(int v=1;v<=G.vexnum;v++)  
    142.         if(!visited[v]) {  
    143.             visited[v]=true;  
    144.             visitVex(G,v);  
    145.             EnQueue(Q,v);  
    146.             while(Q.len!=0)  
    147.             {  
    148.                 DeleteQueue(Q,u);  
    149.                 for(int w=FirstAdjVex(G,u);w>=1;w=NextAdjVex(G,u,w))  
    150.                     if(!visited[w])  
    151.                     {  
    152.                         visited[w]=true;  
    153.                         visitVex(G,v);  
    154.                         EnQueue(Q,w);  
    155.                     }  
    156.             }  
    157.         }  
    158.         cout<<endl;  
    159. }  
    160.   
    161. void main(){  
    162.     ALGraph G;  
    163.     CreateDG(G);  
    164.     PrintGraph(G);  
    165.     cout<<”廣度優先搜索的結果爲:”<<endl;  
    166.     BFSTraverse(G);  
    167. }  
    // Test.cpp : Defines the entry point for the console application.  
    //  
    
    
    
    
    
    #include "stdafx.h" #include "func.h" bool visited[MAX_VERTEX_NUM]; //訪問標識 Status (*VisitFunc) (int v); //函數變量 /************************************************************************/ /* 在無向圖中添加以m,n爲頂點的邊 */ /************************************************************************/ void ArcAdd(ALGraph &G,int m,int n){ ArcNode *p,*h,*q; p = new ArcNode; p->adjvex = m; p->nextarc = NULL; h = q = G.vertices[n].firstarc; if(q == NULL) G.vertices[n].firstarc = p; else { if((p->adjvex)>(q->adjvex)){ p->nextarc = q; G.vertices[n].firstarc = p; } else { while( G.vertices[n].firstarc != NULL && q->nextarc != NULL && (p->adjvex)<(q->adjvex)){ //使鄰接表中邊的數據按大到小排列。 h = q; q = q->nextarc; } if(q->nextarc == NULL&&(p->adjvex)<(q->adjvex)){ q->nextarc = p; } else { p->nextarc = q; h->nextarc = p; } } } } /************************************************************************/ /* 創建無向圖 */ /************************************************************************/ void CreateDG(ALGraph &G){ cout<<"請輸入頂點個數和邊數:"<<endl; cin>> G.vexnum>> G.arcnum; cout<<"請輸入頂點值:"<<endl; for(int i= 1; i<= G.vexnum; i++) { char t; cin>>t; G.vertices[i].data = t; G.vertices[i].firstarc = NULL; } int m, n; for(int k = 1; k<=G.arcnum; k++){ cout<<"請輸入第"<<k<<"條邊的兩個頂點:"<<endl; cin>>m>>n; if(m<= G.vexnum && n <= G.vexnum && m>0 && n>0){ ArcAdd(G, m, n); ArcAdd(G, n, m); } else cout<<"ERROR."<<endl; } } /************************************************************************/ /* 打印鄰接表的無向圖 */ /************************************************************************/ void PrintGraph(ALGraph G) { cout<<"無向圖的創建完成,該圖的鄰接表表示爲:"<<endl; ArcNode *p; for(int i=1; i<=G.vexnum; i++) { if(G.vertices[i].firstarc == NULL) cout<<i<<G.vertices[i].data<<"-->NULL"<<endl; else { p = G.vertices[i].firstarc; cout<<i<<G.vertices[i].data<<"-->"; while(p->nextarc!=NULL) { cout<<p->adjvex<<"-->"; p = p->nextarc; } cout<<p->adjvex<<"-->NULL"<<endl; } } } /************************************************************************/ /* 返回v的第一個鄰接頂點。若頂點在G中沒有鄰接表頂點,則返回“空”。 */ /************************************************************************/ int FirstAdjVex(ALGraph G,int v) { if(G.vertices[v].firstarc) return G.vertices[v].firstarc->adjvex; else return NULL; } /************************************************************************/ /* 返回v的(相對於w的)下一個鄰接頂點。若w是v的最後一個鄰接點,則返回“回”。 */ /************************************************************************/ int NextAdjVex(ALGraph G,int v,int w) { ArcNode *p; if(G.vertices[v].firstarc==NULL) return NULL; else { p = G.vertices[v].firstarc; while(p->adjvex!=w) p = p->nextarc; if(p->nextarc == NULL) return NULL; else return p->nextarc->adjvex; } } void visitVex(ALGraph G, int v){ cout<<G.vertices[v].data<<" "; } /************************************************************************/ /* 廣度優先遍歷圖G */ /************************************************************************/ void BFSTraverse(ALGraph G) { Queue Q; int u; for(int m=1; m<= G.vexnum; m++) visited[m] = false; InitQueue(Q);//藉助輔助隊列。 for(int v=1;v<=G.vexnum;v++) if(!visited[v]) { visited[v]=true; visitVex(G,v); EnQueue(Q,v); while(Q.len!=0) { DeleteQueue(Q,u); for(int w=FirstAdjVex(G,u);w>=1;w=NextAdjVex(G,u,w)) if(!visited[w]) { visited[w]=true; visitVex(G,v); EnQueue(Q,w); } } } cout<<endl; } void main(){ ALGraph G; CreateDG(G); PrintGraph(G); cout<<"廣度優先搜索的結果爲:"<<endl; BFSTraverse(G); }


    分析上述算法,每個頂點至多進一次隊列。遍歷圖的過程實質是通過邊或弧找鄰接點的過程,因此廣度優先搜索遍歷圖的時間複雜度和深度優先搜索遍歷相同,兩者不同之處僅僅在於對頂點訪問的順序不同。

    發表評論
    所有評論
    還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
    相關文章