圖——圖的廣度優先遍歷

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,鄰接頂點的隊列壓入;

相關文章
相關標籤/搜索