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,當用棧來實現的時候,能夠考慮使用遞歸;