1. 程式人生 > >圖的深度優先遍歷(DFS)和廣度優先遍歷(BFS)

圖的深度優先遍歷(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)鄰接矩陣的儲存方式實現:

[cpp] view plain copy print?
  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. #pragma once
  6. #include “targetver.h”
  7. #include <stdio.h>  
  8. #include “stdlib.h”
  9. #include <iostream>
  10. usingnamespace std;  
  11. //巨集定義    
  12. #define TRUE   1    
  13. #define FALSE   0   
  14. #define NULL 0
  15. #define OK    1    
  16. #define ERROR   0  
  17. #define INFEASIBLE -1    
  18. #define OVERFLOW -2  
  19. #define INFINITY   INT_MAX
  20. #define MAX_VERTEX_NUM 30
  21. typedefint Status   ;  
  22. typedefint ElemType ;  
  23. typedefint VrType  ;  
  24. typedefchar VertexType  ;  
  25. /**************************************************************/
  26. / 陣列表示:鄰接矩陣資料結構 
  27. /
  28. /**************************************************************/
  29. typedefstruct ArcCell{  
  30.     VrType adj;                         //頂點關係型別,對無權圖,0/1表示是否相鄰,有權圖表示權值
  31.     ArcCell  *info;                     //弧相關資訊的指標
  32. }ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];  
  33. typedefstruct{  

    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;

    [cpp] view plain copy print?
    1. // Test.cpp : Defines the entry point for the console application.  
    2. //  
    3. #include “stdafx.h” 
    4. bool visited[MAX_VERTEX_NUM];  //訪問標識
    5. Status (*VisitFunc) (int v);   //函式變數
    6. /************************************************************************/
    7. /*   
    8.     確定頂點v在圖G的位置 
    9. */
    10. /************************************************************************/
    11. int LocateVex(MGraph G,VertexType v)  
    12. {  
    13.     for(int i = 0; i<G.vexnum; ++i) {  
    14.         if(G.vexs[i] == v) return i;//找到
    15.     }  
    16.     return -1;//不存在
    17. }  
    18. /************************************************************************/
    19. /*   
    20. */
    21. /************************************************************************/
    22. int FirstAdjVex(MGraph G,int v)  
    23. {  
    24.     int i ;  
    25.     for(i = 0; i<G.vexnum; i++)  
    26.         if( G.arcs[v][i].adj ) return i;  
    27.     if(i == (G.vexnum  -1)) return -1;  
    28.     return -1;   
    29. }  
    30. int NextAdjVex(MGraph G,int v,int w)  
    31. {  
    32.     int i;  
    33.     for( i = w+1; i<G.vexnum; i++)//+1
    34.         if(G.arcs[v][i].adj) return i;  
    35.     if(i == (G.vexnum  -1)) return -1;  
    36.     return -1;  
    37. }  
    38. /************************************************************************/
    39. /* 
    40.  鄰接矩陣的無向圖的建立: 
    41.  註釋的程式碼可以動態生成圖。 
    42. */
    43. /************************************************************************/
    44. void CreatUDG(MGraph &G){  
    45.     cout<<”建立鄰接矩陣的無向圖:”<<endl;  
    46.     int i,j,k,w;  
    47.     //G5的儲存:
    48.     G.arcnum = 8;  
    49.     G.vexnum = 9;  
    50.     for(i=0;i<G.vexnum;++i)  
    51.         for(j=0;j<G.vexnum;++j) {  
    52.             G.arcs[i][j].adj=0;  
    53.             G.arcs[i][j].info=NULL;  
    54.         }  
    55.     G.vexs[0] = ’1’;  
    56.     G.vexs[1] = ’2’;  
    57.     G.vexs[2] = ’3’;  
    58.     G.vexs[3] = ’4’;  
    59.     G.vexs[4] = ’5’;  
    60.     G.vexs[5] = ’6’;  
    61.     G.vexs[6] = ’7’;  
    62.     G.vexs[7] = ’8’;  
    63.     G.arcs[0][1].adj = 1;  
    64.     G.arcs[0][1].info = NULL;  
    65.     G.arcs[1][0].adj = 1;  
    66.     G.arcs[1][0].info = NULL;  
    67.     G.arcs[1][3].adj = 1;  
    68.     G.arcs[1][3].info = NULL;  
    69.     G.arcs[3][1].adj = 1;  
    70.     G.arcs[3][1].info = NULL;  
    71.     G.arcs[3][7].adj = 1;  
    72.     G.arcs[3][7].info = NULL;  
    73.     G.arcs[7][3].adj = 1;  
    74.     G.arcs[7][3].info = NULL;  
    75.     G.arcs[7][4].adj = 1;  
    76.     G.arcs[7][4].info = NULL;  
    77.     G.arcs[4][7].adj = 1;  
    78.     G.arcs[4][7].info = NULL;  
    79.     G.arcs[4][1].adj = 1;  
    80.     G.arcs[4][1].info = NULL;  
    81.     G.arcs[1][4].adj = 1;  
    82.     G.arcs[1][4].info = NULL;  
    83.     G.arcs[0][2].adj = 1;  
    84.     G.arcs[0][2].info = NULL;  
    85.     G.arcs[2][0].adj = 1;  
    86.     G.arcs[2][0].info = NULL;  
    87.     G.arcs[2][5].adj = 1;  
    88.     G.arcs[2][5].info = NULL;  
    89.     G.arcs[5][2].adj = 1;  
    90.     G.arcs[5][2].info = NULL;  
    91.     G.arcs[5][6].adj = 1;  
    92.     G.arcs[5][6].info = NULL;  
    93.     G.arcs[6][5].adj = 1;  
    94.     G.arcs[6][5].info = NULL;  
    95.     G.arcs[6][2].adj = 1;  
    96.     G.arcs[6][2].info = NULL;  
    97.     G.arcs[2][6].adj = 1;  
    98.     G.arcs[2][6].info = NULL;  
    99.     return ;  
    100.     /* 
    101.     char v1,v2; 
    102.     cout<<”請輸入無向圖頂點個數和邊數:”<<endl; 
    103.     cin>>G.vexnum>>G.arcnum; 
    104.     cout<<”請輸入”<<G.vexnum<<”個頂點的值:”<<endl; 
    105.     for(i=0;i<G.vexnum;++i) cin>>G.vexs[i]; 
    106.     for(i=0;i<G.vexnum;++i) 
    107.         for(j=0;j<G.vexnum;++j) { 
    108.             G.arcs[i][j].adj=0; 
    109.             G.arcs[i][j].info=NULL; 
    110.         } 
    111.         for( k=1;k<=G.arcnum;++k){ 
    112.             cout<<”請輸入第”<<k<<”條邊的兩個頂點值和它們的權重:”<<endl; 
    113.             cin>>v1>>v2>>w; 
    114.             i = LocateVex(G,v1);   j=LocateVex(G,v2);  
    115.             G.arcs[i][j].adj=w; 
    116.             G.arcs[j][i]=G.arcs[i][j]; 
    117.         } 
    118.         */
    119. }  
    120. /************************************************************************/
    121. /* 有向圖鄰接矩陣的建立 
    122. */
    123. /************************************************************************/
    124. void CreatDG(MGraph &G){  
    125.     int i,j,k,w;  
    126.     char v1,v2;  
    127.     G.arcnum = 8;  
    128.     G.vexnum = 9;  
    129.     cout<<”請輸入有向圖頂點個數和邊數:”;  
    130.     cin>> G.vexnum>> G.arcnum;  
    131.     cout<<”請輸入”<<G.vexnum<<“個頂點的值:”<<endl;  
    132.     for(i=0;i<G.vexnum;++i) cin>>G.vexs[i];  
    133.     for(i=0;i<G.vexnum;++i)  
    134.         for(j=0;j<G.vexnum;++j) {  
    135.             G.arcs[i][j].adj = 0;  
    136.             G.arcs[i][j].info = NULL;  
    137.         }  
    138.         for( k=1;k<=G.arcnum;++k){  
    139.             cout<<”請輸入第”<<k<<“條邊的兩個頂點值和它們的權重:”<<endl;  
    140.             cin>>v1>>v2>>w;  
    141.             i= LocateVex(G,v1);   j = LocateVex(G,v2);   
    142.             G.arcs[i][j].adj = w;  
    143.         }  
    144. }  
    145. void visitVex(MGraph G, int v){  
    146.     cout<<G.vexs[v]<<” ”;  
    147. }  
    148. /************************************************************************/
    149. /*  以V為出發點對圖G 進行遞迴地DFS 搜尋 
    150. */
    151. /************************************************************************/
    152. void DFS(MGraph G,int v){  
    153.     visited[v] = true;  
    154.     visitVex( G,  v); //訪問第v 個頂點
    155.     for(int w = FirstAdjVex(G,v); w>=0; w = NextAdjVex(G,v,w)){  
    156.         if(!visited[w]) DFS(G,w); //w未訪問過,遞迴DFS搜尋
    157.     }  
    158. }  
    159. /************************************************************************/
    160. /*      
    161. 無向圖的深度遍歷        
    162. */
    163. /************************************************************************/
    164. void DFSTraverse(MGraph G){//
    165.     int v;  
    166.     for( v = 0; v < G.vexnum; ++v) visited[v] = false;  
    167.     for( v = 0; v < G.vexnum; )   
    168.         if(!visited[v]) DFS( G, v); //v未訪問過,從vi開始DFS搜尋
    169.         ++v;//不要像書上寫的那樣,++v放到for語句,這樣會導致多出一次訪問
    170. }  
    171. void printMGraph(MGraph G){  
    172.     cout<<”鄰接矩陣已經建立,鄰接矩陣為:”<<endl;  
    173.     for(int i=0;i<G.vexnum;i++){  
    174.         for(int j=0;j<G.vexnum;j++)  
    175.             cout<<G.arcs[i][j].adj<<” ”;  
    176.         cout<<endl;  
    177.     }  
    178. }  
    179. void main(){  
    180.     MGraph G;  
    181.     CreatUDG(G);  
    182.     printMGraph(G);  
    183.     cout<<”無向圖鄰接矩陣的深度遍歷結果:”<<endl;  
    184.     DFSTraverse(G);  
    185. }  
    // 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) 鄰接表的表示實現方式 [cpp] view plain copy print?
    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. #pragma once
    6. #include “targetver.h”
    7. #include <stdio.h>  
    8. #include “stdlib.h”
    9. #include <iostream>
    10. usingnamespace std;  
    11. //巨集定義    
    12. #define TRUE   1    
    13. #define FALSE   0   
    14. #define NULL 0
    15. #define OK    1    
    16. #define ERROR   0  
    17. #define INFEASIBLE -1    
    18. #define OVERFLOW -2  
    19. #define INFINITY   INT_MAX
    20. #define MAX_VERTEX_NUM 30
    21. typedefint Status   ;  
    22. typedefint ElemType ;  
    23. typedefint VrType  ;  
    24. typedefchar VertexType  ;  
    25. /************************************************************************/
    26. /*  鄰接表示的圖資料結構 
    27. */
    28. /************************************************************************/
    29. //定義邊結點,即表節點
    30. typedefstruct ArcNode   
    31. {  
    32.     int adjvex;             //弧所指的頂點位置
    33.     ArcNode *nextarc;       //指向下一條弧的指標
    34. }ArcNode;  
    35. //定義頂點節點,即頭節點
    36. typedefstruct VNode    
    37. {  
    38.     VertexType data;        //頂點資訊
    39.     ArcNode *firstarc;      //指向第一條依附該頂點的弧的指標
    40. }VNode,AdjList[MAX_VERTEX_NUM];  
    41. //定義無向圖   
    42. typedefstruct
    43. {  
    44.     AdjList vertices;  
    45.     int vexnum,arcnum;   //圖的當前頂點數和弧數
    46. }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;
    [cpp] view plain copy print?
    1. // Test.cpp : Defines the entry point for the console application.  
    2. //  
    3. #include “stdafx.h” 
    4. bool visited[MAX_VERTEX_NUM];  //訪問標識
    5. Status (*VisitFunc) (int v);   //函式變數
    6. /************************************************************************/
    7. /* 在無向圖中新增以m,n為頂點的邊 
    8. */
    9. /************************************************************************/
    10. void ArcAdd(ALGraph &G,int m,int n){  
    11.     ArcNode *p,*h,*q;  
    12.     p = new ArcNode;  
    13.     p->adjvex = m;  
    14.     p->nextarc = NULL;  
    15.     h = q = G.vertices[n].firstarc;  
    16.     if(q == NULL)  
    17.         G.vertices[n].firstarc = p;  
    18.     else {   
    19.         if((p->adjvex)>(q->adjvex)){   
    20.             p->nextarc = q;  
    21.             G.vertices[n].firstarc = p;  
    22.         }  
    23.         else {   
    24.             while( G.vertices[n].firstarc != NULL && q->nextarc != NULL && (p->adjvex)<(q->adjvex)){ //使鄰接表中邊的資料按大到小排列。  
    25.                 h = q;  
    26.                 q = q->nextarc;  
    27.             }  
    28.             if(q->nextarc == NULL&&(p->adjvex)<(q->adjvex)){    
    29.                 q->nextarc = p;  
    30.             }  
    31.             else {    
    32.                 p->nextarc = q;  
    33.                 h->nextarc = p;  
    34.             }  
    35.         }  
    36.     }  
    37. }  
    38. /************************************************************************/
    39. /* 
    40. 建立無向圖 
    41. */
    42. /************************************************************************/
    43. void CreateDG(ALGraph &G){    
    44.     cout<<”請輸入頂點個數和邊數:”<<endl;  
    45.     cin>> G.vexnum>> G.arcnum;  
    46.     cout<<”請輸入頂點值:”<<endl;  
    47.     for(int i= 1; i<= G.vexnum; i++) {  
    48.         char t;  
    49.         cin>>t;  
    50.         G.vertices[i].data = t;  
    51.         G.vertices[i].firstarc = NULL;  
    52.     }  
    53.     int m, n;  
    54.     for(int k = 1; k<=G.arcnum; k++){  
    55.         cout<<”請輸入第”<<k<<“條邊的兩個頂點:”<<endl;  
    56.         cin>>m>>n;  
    57.         if(m<= G.vexnum && n <= G.vexnum && m>0 && n>0){  
    58.             ArcAdd(G, m, n);  
    59.             ArcAdd(G, n, m);  
    60.         }  
    61.         else  cout<<“ERROR.”<<endl;   
    62.     }  
    63. }  
    64. /************************************************************************/
    65. /* 列印鄰接表的無向圖       
    66. */
    67. /************************************************************************/
    68. void PrintGraph(ALGraph G)    
    69. {  
    70.     cout<<”無向圖的建立完成,該圖的鄰接表表示為:”<<endl;  
    71.     ArcNode *p;  
    72.     for(int i=1; i<=G.vexnum; i++)  
    73.     {  
    74.         if(G.vertices[i].firstarc == NULL)  
    75.             cout<<i<<G.vertices[i].data<<”–>NULL”<<endl;  
    76.         else
    77.         {  
    78.             p = G.vertices[i].firstarc;  
    79.             cout<<i<<G.vertices[i].data<<”–>”;  
    80.             while(p->nextarc!=NULL)  
    81.             {  
    82.                 cout<<p->adjvex<<”–>”;  
    83.                 p = p->nextarc;  
    84.             }  
    85.             cout<<p->adjvex<<”–>NULL”<<endl;  
    86.         }  
    87.     }  
    88. }  
    89. /************************************************************************/
    90. /*     返回v的第一個鄰接頂點。若頂點在G中沒有鄰接表頂點,則返回“空”。    
    91. */
    92. /************************************************************************/
    93. int FirstAdjVex(ALGraph G,int v)  
    94. {   
    95.     if(G.vertices[v].firstarc)  
    96.         return G.vertices[v].firstarc->adjvex;  
    97.     else
    98.         return NULL;  
    99. }  
    100. /************************************************************************/
    101. /*    
    102.   返回v的(相對於w的)下一個鄰接頂點。若w是v的最後一個鄰接點,則返回“回”。 
    103. */
    104. /************************************************************************/
    105. int NextAdjVex(ALGraph G,int v,int w)     
    106. {  
    107.     ArcNode *p;  
    108.     if(G.vertices[v].firstarc==NULL)  
    109.         return NULL;  
    110.     else {  
    111.         p = G.vertices[v].firstarc;  
    112.         while(p->adjvex!=w) p = p->nextarc;  
    113.         if(p->nextarc == NULL) return NULL;  
    114.         elsereturn p->nextarc->adjvex;  
    115.     }  
    116. }  
    117. void visitVex(ALGraph G, int v){  
    118.     cout<<G.vertices[v].data<<” ”;  
    119. }  
    120. /************************************************************************/
    121. /*      
    122. 無向圖的深度遍歷        
    123. */
    124. /************************************************************************/
    125. //從第v個頂點出發遞迴地深度優先遍歷圖G
    126. void DFS(ALGraph G,int v)  
    127. {  
    128.     visited[v] = true;  
    129.     visitVex(G, v);  
    130.     for(int w = FirstAdjVex(G,v);w >= 1; w = NextAdjVex(G,v,w))  
    131.         if(!visited[w]) DFS(G,w);  
    132. }  
    133. //對圖G作深度優先遍歷
    134. void DFSTraverse(ALGraph G)  
    135. {   
    136.     for(int v = 1; v <= G.vexnum; v++) visited[v]=false;  
    137.     for(int m = 1; m <= G.vexnum; m++)  
    138.         if(!visited[m]) DFS(G,m);  
    139. }  
    140. void main(){  
    141.     ALGraph G;  
    142.     CreateDG(G);  
    143.     PrintGraph(G);  
    144.     DFSTraverse(G);  
    145. }  
    // 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、… 的頂點。

    實現:

    [cpp]

    相關推薦

    深度優先DFS)廣度優先BFS

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

    鄰接表實現--深度優先DFS廣度優先BFS

              圖論中一個基本的概念就是遍歷。就是訪問到圖的每一個頂點,同時每個頂點只訪問一次。           DFS和BFS的概念和思路網上說明的很詳細了。但是網上很多程式碼實現有缺陷,基本都沒有考慮圖不連通的情況,比如某個頂點A和其它任何一個頂點都不關聯,

    深度優先(DFS)廣度優先(BFS)算法分析

    search 圖的深度優先遍歷 eight 一個 ima 圖的廣度優先遍歷 spa color 一句話 1. 深度優先遍歷   深度優先遍歷(Depth First Search)的主要思想是:     1、首先以一個未被訪問過的頂點作為起始頂點,沿當前頂點的邊走到未訪

    演算法: 無向深度優先搜尋(dfs)廣度優先搜尋(bfs)

    更新:DFS和BFS是應用廣泛而實現簡便的演算法,但有2個小點需要稍稍注意一下。 對於DFS來說,可以用遞迴,也可以用迭代。對於一張較大的圖,迭代是優於遞迴的,因為遞迴要維護一個函式呼叫棧。小心stackoverflow喔。 對於BFS來說,實現起來需要注意

    的基本演算法--深度優先搜尋(dfs) 廣度優先搜尋(bfs)

    # 圖 # 0 # / | \ # 1 2 - 4 # / # 3 m = 999999 # 代表沒有連線 a =

    深度優先DFS廣度優先BFS

    1 建立測試圖(鄰接矩陣和鄰接表儲存形式) 首先建立一個圖用於後續程式碼的測試,在此以無向圖為例,且所有邊的權值都為1。儲存方式分別為鄰接矩陣和鄰接表(見上一篇介紹) 鄰接矩陣: class Graph{ constructor(v,vr){ let len = v.le

    | 兩種方式:深度優先搜尋DFS、深搜廣度優先搜尋BFS、廣搜

    前邊介紹了有關圖的 4 種儲存方式,本節介紹如何對儲存的圖中的頂點進行遍歷。常用的遍歷方式有兩種:深度優先搜尋和廣度優先搜尋。 深度優先搜尋(簡稱“深搜”或DFS) 圖 1 無向圖 深度優先搜尋的過程類似於樹的先序遍歷,首先從例

    演算法-深度優先搜尋演算法dfs廣度優先搜尋演算法bfs

    一、前提須知圖是一種資料結構,一般作為一種模型用來定義物件之間的關係或聯絡。物件:頂點(V)表示;物件之間的關係或者關聯:通過圖的邊(E)來表示。一般oj題中可能就是點與點,也有可能是具體生活中的物體圖

    深度優先DFS廣度優先BFS--解析

    圖的資料結構不像二叉樹那樣,有明顯的父子節點和兄弟節點的關係,它只有一個關係就是鄰接關係。故對圖中頂點的訪問要採用標誌陣列(來確定改結點是否被訪問,去除重複訪問)。並且對圖的深度遍歷採用遞迴的方式是較高效的。 1.深度遍歷(DFS) #include<iostream

    演算法----深度優先搜尋DFS廣度優先搜尋BFS

    圖的遍歷的定義:從圖的某個頂點出發訪問圖中所有的點,且每個頂點僅被訪問一次。 深度優先搜尋DFS: 準備:指定的起始點和終點,確定好當前點與鄰接點之間的偏移值、結束搜尋的條件、符合訪問的點所需條件、回溯處理; (1)若當前點的鄰接點有未被訪問的,則選一個進行訪問; (2)若當前點的鄰接點都不符合訪問條

    深度優先廣度優先

    圖的遍歷就是從圖中某個頂點出發,按某種方法對圖中所有頂點訪問且僅訪問一次。 圖的遍歷演算法是求解圖的連通性問題、拓撲排序和求關鍵路徑等演算法的基礎 深度優先遍歷(depth-first search):類似於樹的先根遍歷,是樹的先根遍歷的推廣 (可以採用遞迴和藉助棧的非遞迴方式實現)

    深度優先廣度優先Java實現

    深度優先遍歷 深度優先遍歷,從初始訪問結點出發,我們知道初始訪問結點可能有多個鄰接結點,深度優先遍歷的策略就是首先訪問第一個鄰接結點,然後再以這個被訪問的鄰接結點作為初始結點,訪問它的第一個鄰接結點。總結起來可以這樣說:每次都在訪問完當前結點後首先訪問當前結點的

    無向深度優先廣度優先鄰接連結串列

    我選的是鄰接連結串列,建立如下圖所示的圖: 我把它畫出來,圖是這樣子的: 對於深度優先遍歷:是從一個頂點v出發,一步一步地向前推進,當找不到未訪問過的頂點時,也是一步一步地回退。其過程類似於用棧求解迷宮問題的搜尋方式。 比如上面這個圖:我從4這個頂點開始遍歷,它

    Java實現深度廣度優先算法

    lan 圖結構 廣度搜索 源代碼下載 源代碼 earch isempty 學習 ole 概述: 近期要學習寫網絡爬蟲。所以把圖的深度和廣度搜索都再溫習一下。 圖結構展示: 實現過程: 首先,我們來看看圖結構在代碼中的實現。有三塊邏輯: 1.圖中的節點

    深度優先廣度優先

    優先 ges sky 深度優先 們的 老師 ear blog earch 圖的遍歷之深度優先和廣度優先 深度優先遍歷 假設給定圖G的初態是所有頂點均未曾訪問過。在G中任選一頂點v為初始出發點(源點),則深度優先遍歷可定義如下:首先訪問出發點v,並將其標記為已訪問過;然後依

    深度優先搜索廣度優先搜索

    順序 如果 一個 depth cde ava nbsp github 深度優先搜索遍歷 本章會先對圖的深度優先搜索和廣度優先搜索進行介紹,然後再給出C/C++/Java的實現。 目錄 1. 深度優先搜索的圖文介紹 1.1 深度優先搜索介紹 1.2 深度優先搜索圖解

    小朋友學資料結構16:基於鄰接矩陣的的深度優先廣度優先

    觀察下面兩個無向圖: 這兩個圖其實是一樣的,只是畫法不同罷了。第一張圖更有立體感,第二張圖更有層次感,並且把A點置為頂點(事實上圖的任何一點都可以做為頂點)。 一、用陣列來存放頂點 vexs[0] = ‘A’ vexs[1] = ‘B’ vexs[2] = ‘C’ ve

    PHP實現二叉樹的深度優先前序、中序、後序廣度優先層次

    前言: 深度優先遍歷:對每一個可能的分支路徑深入到不能再深入為止,而且每個結點只能訪問一次。要特別注意的是,二叉樹的深度優先遍歷比較特殊,可以細分為先序遍歷、中序遍歷、後序遍歷。具體說明如下: 前序遍歷:根節點->左子樹->右子樹 中序遍歷:左子樹->根節點->右子樹 後

    Java實現深度廣度優先演算法

    <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/

    基於鄰接表儲存的深度優先廣度優先

    一.深度優先遍歷是連通圖的一種遍歷方法:   設x是當前被訪問頂點,在對x做過訪問標記後,選擇一條從x出發的未檢測過的邊(x, y)。若發現頂點y已訪問過,則重新選擇另一條從x出發的未檢測過的邊,否則沿邊(x,y) 到達未曾訪問過的y,對y訪問並將其標記為已訪問過;