1. 程式人生 > 實用技巧 >資料結構_圖(鄰接矩陣&深度優先&廣度優先)

資料結構_圖(鄰接矩陣&深度優先&廣度優先)

要點

重點在於掌握圖的基本概念和儲存,以及求關鍵路徑、最短路徑、拓撲排序的方法。

概念

圖G由兩個集合V和E組成,記為G=(V,E),其中V是頂點的有窮非空集合,E是V中頂點偶對 (稱為邊)的有窮集合。通常,也將圖G的頂點集和邊集分別記為V(G)和E(G)。E(G)可以是 空集。若E(G)為空,則圖G只有頂點而沒有邊。

圖的儲存結構

鄰接矩陣

鄰接矩陣

圖的遍歷

圖的遍歷也是從某個頂點出發,沿著某條搜尋路徑對圖中每個頂點各做一次且僅做一次訪問, 常用的遍歷演算法包括以下深度優先和廣度優先兩種

程式碼實現

  1 #include<iostream>
  2 #include<queue>
  3
#include<string.h> 4 using namespace std; 5 #define MaxInt 10000 6 #define Max_V 100 7 typedef char Vtype;//頂點資料型別是字元型 8 typedef int Arctype;//邊的權值是整形 9 bool visited[MaxInt]; 10 //圖的鄰接矩陣儲存方式 11 typedef struct 12 { 13 Vtype Vdata[Max_V]; //頂點資料 14 Arctype arcs[Max_V][Max_V]; //鄰接矩陣 15
int vexnum,arcnum; //頂點數和邊數 16 }AMGraph; 17 18 19 //鄰接矩陣建立無向網 20 int LocateVex(AMGraph G,Vtype v); 21 void CreateGraph(AMGraph &G) 22 { 23 cout<<"請輸入無向網的頂點個數和邊的條數:"<<endl; 24 cin>>G.vexnum>>G.arcnum; 25 cout<<"請依次輸入頂點的資訊:"<<endl; 26 for
(int i=0;i<G.vexnum;i++) 27 cin>>G.Vdata[i]; //此處存放v1 v2 等等節點的名字 28 for(int i=0;i<G.vexnum;i++) 29 for(int j=0;j<G.vexnum;j++) 30 G.arcs[i][j] = MaxInt; 31 32 cout<<"請依次輸入邊的倆個頂點資訊和邊的權值:"<<endl; 33 for(int k=0;k<=G.vexnum;k++) 34 { 35 int i,j; 36 char v1,v2; 37 Arctype w; 38 39 cin>>v1>>v2>>w; 40 i = LocateVex(G,v1); 41 j = LocateVex(G,v2); 42 G.arcs[i][j] = w; 43 G.arcs[j][i] = G.arcs[i][j]; 44 } 45 } 46 void Initvisited(AMGraph G,bool v[]) 47 { 48 for(int i=0;i<G.vexnum;i++) 49 v[i] = false; 50 } 51 //深度遍歷無向網 52 void DFS_AM(AMGraph G,int v) 53 { 54 int j; 55 if(!visited[v]){ 56 cout<<G.Vdata[v]<<"->"; 57 visited[v] = true; 58 } 59 for(j=0;j<G.vexnum;j++) 60 { 61 if(G.arcs[v][j]!=MaxInt&&!visited[j]) 62 { 63 DFS_AM(G,j); 64 } 65 } 66 } 67 68 //廣度優先遍歷無向網 69 void BFS(AMGraph G,int v) 70 { 71 queue<Vtype> q; 72 int i; 73 if(!visited[v]) 74 { 75 cout<<G.Vdata[v]<<"->"; 76 q.push(v); 77 visited[v] = true; 78 } 79 while(!q.empty()) 80 { 81 i = q.front(); 82 q.pop(); 83 for(int j=0;j<G.vexnum;j++) 84 { 85 if(G.arcs[i][j]!=MaxInt&&!visited[j]) 86 { 87 cout<<G.Vdata[j]<<"->"; 88 q.push(j); 89 visited[j] = true; 90 } 91 } 92 } 93 } 94 95 int LocateVex(AMGraph G,Vtype v) 96 { 97 int i; 98 for(i=0;i<G.vexnum;i++) 99 { 100 if(G.Vdata[i] ==v) 101 return i; 102 } 103 return -1; 104 } 105 106 int main() 107 { 108 AMGraph m; 109 CreateGraph(m); 110 Initvisited(m,visited); 111 cout<<"深度優先遍歷:"<<endl; 112 DFS_AM(m,0); 113 Initvisited(m,visited); 114 //memset(visited,false,sizeof(visited)); 115 cout<<endl; 116 cout<<"廣度優先遍歷:"<<endl; 117 BFS(m,0); 118 return 0; 119 }

總結

深度遍歷的思想是遞迴,類似於先序遍歷輸出,廣度優先遍歷涉及到了棧的知識,一個節點入棧之後接下來入棧的便是上一個入棧節點的子節點(孩子),這樣就實現了廣度優先。