圖——圖的深度優先遍歷

1,深度優先(DFS):ios

 

       1,先選擇一條邊走,有多條邊後,再選擇一條走,直到無邊可走,回退;算法

       2,再選擇另外一條邊走;數組

       3,特色:只要在當前的頂點上面能夠有邊走到其它頂點,就深刻的走下去;函數

      

2,深度優先算法:測試

       1,原料:class LinkStack<T>;spa

       2,步驟:code

              1,將起始頂點壓入棧中;blog

              2,彈出棧頂頂點 V,判斷是否已經標記(標記:轉 2,未標記:轉 3);遞歸

              3,標記頂點 V,並將頂點 V 的鄰接頂點壓入棧中;隊列

              4,判斷棧是否爲空(非空:轉 2,空:結束);             

 

3,深度優先算法示例:

 

      

4,深度優先算法流程圖:

 

  1,標記、壓入鄰接頂點;

 

5,深度優先算法實現:

 1    /* 實現深度優先算法的函數;核心思想是二叉樹先序遍歷核心思想(非遞歸法版本) */
 2     SharedPointer< Array<int> > DFS(int i)
 3     {
 4         DynamicArray<int>* ret = NULL;  // 返回值是一個數組
 5         if( (0 <= i) && (i < vCount()) )  // 參數合法
 6         {
 7             LinkStack<int> s;  // 壓入鄰接頂點的棧
 8             LinkQueue<int> r;  // 壓入遍歷值的隊列
 9             DynamicArray<bool> visited(vCount());  // 訪問標記數組
10 
11             /* 將標記裏面的值初始化爲未有訪問 */
12             for(int j=0; j<visited.length(); j++)
13             {
14                 visited[j] = false;
15             }
16 
17             s.push(i);  // 初始頂點壓入棧中
18 
19             while( s.size() > 0 )  // 有頂點就要繼續
20             {
21                 int v = s.top();  // 獲得棧頂的元素
22 
23                 s.pop();  // 彈出棧頂元素
24 
25                 if( !visited[v] )  // 頂點未有訪問
26                 {
27                     SharedPointer< Array<int> > aj = getAdgacent(v);  // 獲得 v 的全部鄰接頂點
28 
29                     /* 將 v 的全部鄰接頂點壓入棧中 */
30                     for(int j=aj->length()-1; j>=0; j--)
31                     {
32                         s.push((*aj)[j]);  // 將鄰接頂點逐個壓入棧中
33                     }
34 
35                     r.add(v);  // 將 v 壓入隊列中
36 
37                     visited[v] = true;  // 將 v 標記位已經訪問
38                 }
39             }
40 
41             ret = toArray(r);  // 將隊列轉換爲數組
42         }
43         else
44         {
45             THROW_EXCEPTION(InvalidParameterException, "Index i is invalid ...");
46         }
47 
48         return ret;
49     }

 

6,深度優先算法實現的測試代碼:

 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.DFS(0);
39 
40     for(int i=0; i<sa->length(); i++)
41     {
42         cout << (*sa)[i] << " ";
43    }
44 
45     return 0;
46 }

 

7,如何使用二叉樹先序遍歷的思想遍歷圖?

       1,深度優先思想使用的就是二叉樹先序遍歷的思想,先序遍歷是遞歸完成的,深度優先算法也能夠遞歸完成;

      

8,遞歸法實現深度優先:

 

       1,問題劃分;

       2,定義功能:DFS(graph, vex)

 

              1,以頂點 vex 爲起始頂點深度優先遍歷 graph;

       3,功能函數代碼實現:

 1 /* 定義深度優先算法的遞歸函數 */
 2 template < typename V, typename E>
 3 void DFS(Graph<V, E>& g, int v, Array<bool>& visited)
 4 {
 5     if( (0 <= v) && (v < g.vCount()) )
 6     {
 7         cout << v << endl;  // 訪問的方式是打印
 8 
 9         visited[v] = true;  // 設置訪問標記
10 
11         SharedPointer< Array<int> > aj = g.getAdgacent(v);  // 獲取 v 的鄰接頂點
12 
13         /* v 是否有鄰接頂點,有的話就遞歸進行深度優先算法的遍歷 */
14         for(int i=0; i<aj->length(); i++)
15         {   
16        /* 若是沒有進行訪問,就進行深度優先遍歷 */
17             if( !visited[(*aj)[i]])
18             {
19                 DFS(g, (*aj)[i], visited);  // 遞歸調用
20             }
21         }
22     }
23     else
24     {
25         THROW_EXCEPTION(InvalidParameterException, "Index v is invalid ...");
26     }
27 }

  4,深度優先代碼實現:

 1 /* 遞歸法深度優先遍歷圖,第一個參數是要被遍歷的圖,第二個參數是遍歷的起始頂點 */
 2 template < typename V, typename E >
 3 void DFS(Graph<V, E>& g, int v)
 4 {
 5 DynamicArray<bool> visited(g.vCount());  // 標記頂點是否被訪問過
 6 
 7     /* 爲每個頂點設置是否被訪問的初始值 */
 8     for(int i=0; i<visited.length();i++)
 9     {
10         visited[i] = false;
11 }
12 
13     DFS(g, v, visited);
14 }

 

9,小結:

       1,深度優先按照「先序遍歷的方式」對頂點進行訪問;

       2,深度優先算法的核心是棧的使用;

       3,深度優先和廣度優先的惟一不一樣在於棧或隊列的使用;

       4,深度優先算法能夠使用遞歸的方式實現;

              1,深度優先使用棧來完成的而且是先序遍歷的思想,則能夠考慮使用遞歸的方式來實現;

              2,當用棧來實現的時候,能夠考慮使用遞歸;

相關文章
相關標籤/搜索