1,前面兩篇博文實現了鄰接矩陣和鄰接鏈表法實現圖的數據結構,什麼狀況下選擇合適的圖的類型?從時間複雜度角度來對比下;ios
2,時間複雜度的對比分析:算法
1,鄰接矩陣法操做性能更好、效率更高,更在乎性能,則選擇鄰接矩陣法;數組
2,鏈表矩陣法在空間使用率上更好,當環境資源緊張、內存比較小,選擇鄰接鏈表法;數據結構
3,小結論:函數
1,MatrixGraph 適用於內存資源富足的場合(性能較好);性能
2,ListGraph 適用於內存資源受限的場合(節省空間);測試
4,圖的遍歷:spa
1,從圖中的某一個頂點出發,沿着一些邊訪問圖中的其它頂點,使得每一個頂點最多被訪問一次;code
2,注意:從某個頂點出發進行遍歷,不必定可以訪問到圖中的全部頂點;對象
1,當始發頂點沒有任何鄰接頂點時;
5,圖的遍歷方式:
1,廣度優先(Breadth First Search):
1,以二叉樹層次遍歷的思想對圖進行遍歷;
2,深度優先(Depth First Search):
1,以二叉樹先序遍歷的思想對圖進行遍歷;
6,廣度優先(BFS):
1,樹的廣度優先算法須要原材料:隊列;
7,廣度優先算法:
1,原料:class LinkQueue<T>;
2,步驟:
1,將起始頂點壓入隊列中;
2,隊頭頂點 V 彈出,判斷是否已經標記(標記:轉 2,未標記:轉 3);
1,每一個頂點只能訪問一次,若是發現隊頭頂點已經打上標記,則已經訪問過了,直接扔掉;
3,標記頂點,並將頂點 V 的鄰接頂點壓入隊列中;
1,沒有訪問過的頂點的操做;
4,判斷隊列是否爲空(非空:轉 2,空:結束);
8,廣度優先算法示例:
9,廣度優先算法流程圖:
1,比樹多了個標記數組,由於樹結點的孩子不多是此結點的父親或祖先,可是圖卻能夠是,因此要標記數組;
10,廣度優先算法實現:
1 /* 廣度優先算法,參數 i 爲起始的頂點編號,圖中的這個編號才具備惟一辨識性;以層次的方式對定點進行訪問 ; 廣度優先和深度優先惟一不一樣在於棧或隊列的使用,使用隊列存儲鄰接頂點則爲廣度優先,使用棧存儲鄰接頂點則爲深度優先 ; 爲了保持接口的一致性,仿照樹裏面層次遍歷的操做設置函數接口 */ 2 SharedPointer< Array<int> > BFS(int i) 3 { 4 DynamicArray<int>* ret = NULL; // 存儲返回的頂點編號,要反應訪問頂點編號的前後次序 5 6 if( (0 <= i) && (i < vCount()) ) 7 { 8 LinkQueue<int> q; // 存放圖的將要可能被遍歷結點 9 LinkQueue<int> r; // 存放圖的遍歷後的結點 10 DynamicArray<bool> visited(vCount()); //存儲是否頂點是否被遍歷的標記 11 12 /* 初始的標記數組值設置 */ 13 for(int i=0; i<visited.length(); i++) 14 { 15 visited[i] = false; 16 } 17 18 q.add(i); // 向將要被可能訪問結點的隊列中加入元素 19 20 /* 遍歷循環開始 */ 21 while( q.length() > 0 ) 22 { 23 int v = q.front(); // 獲得隊列頭部的頂點值 24 q.remove(); // 拿出這個頂點 25 26 if( !visited[v] ) // 判斷是否被遍歷過 27 { 28 SharedPointer< Array<int> > aj = getAdgacent(v); // 拿到 v 頂點的鄰接頂點並放到數組中 29 30 /* 將鄰接頂點放到隊列中 */ 31 for(int j=0; j<aj->length(); j++) 32 { 33 q.add((*aj)[j]); // 將鄰接頂點放到隊列中 34 } 35 36 r.add(v); // 將頂點放到訪問隊列中去 37 38 visited[v] = true; // 將訪問標記設爲訪問 39 } 40 } 41 42 ret = toArray(r); // 將隊列轉換爲數組 43 } 44 else 45 { 46 THROW_EXCEPTION(InvalidParameterException, "Index i is invalid ..."); 47 } 48 49 return ret; 50 }
11,廣度優先算法實現的測試代碼:
1 #include <iostream> 2 #include "MatrixGraph.h" 3 4 using namespace std; 5 using namespace DTLib; 6 7 int main() 8 { 9 MatrixGraph<9, char, int> g; 10 const char* VD = "ABEDCGFHI"; 11 12 for(int i=0; i<9; i++) 13 { 14 g.setVertex(i, VD[i]); // 設置頂點相關的值爲字符串 VD 中的內容 15 } 16 17 g.setEdge(0, 1, 0); // 無向圖、特殊的有向圖,因此每一個點之間的鄰接矩陣對稱, 這裏權值爲 0,只關心是否鏈接,不關心權值 18 g.setEdge(1, 0, 0); 19 g.setEdge(0, 3, 0); 20 g.setEdge(3, 0, 0); 21 g.setEdge(0, 4, 0); 22 g.setEdge(4, 0, 0); 23 g.setEdge(1, 2, 0); 24 g.setEdge(2, 1, 0); 25 g.setEdge(1, 4, 0); 26 g.setEdge(4, 1, 0); 27 g.setEdge(2, 5, 0); 28 g.setEdge(5, 2, 0); 29 g.setEdge(3, 6, 0); 30 g.setEdge(6, 3, 0); 31 g.setEdge(4, 6, 0); 32 g.setEdge(6, 4, 0); 33 g.setEdge(6, 7, 0); 34 g.setEdge(7, 6, 0); 35 g.setEdge(7, 8, 0); 36 g.setEdge(8, 7, 0); 37 38 SharedPointer< Array<int> > sa = g.BFS(0); 39 40 for(int i=0; i<sa->length(); i++) 41 { 42 cout << (*sa)[i] << " "; 43 } 44 45 return 0; 46 }
12,標號是圖中惟一能夠表示頂點的標誌,要利用好;
13,父類中實現其餘時,能夠調用子類中對純虛函數的實現,由於當子類建立對象後,父類中的全部函數都被繼承到了子類當中;
14,小結:
1,MatrixGraph 適用於資源富足的場合;
2,ListGraph 適用於資源受限的場合;
1,時間複雜度高;
3,廣度優先按照「層次的方式」對定點進行訪問;
1,同樹的層次遍歷;
4,廣度優先算法的核心是隊列的使用;
1,鄰接頂點的隊列壓入;