算法系列—圖的深度優先搜尋(遞迴)/C++
阿新 • • 發佈:2019-02-08
圖的遍歷是指從圖的某一個頂點出發,按照某種方法沿著邊對圖中的頂點全部訪問一次。
ps:樹是一幅無環連通圖。互不相連的樹組成的集合 稱為森林。
連通圖的生成樹是它的一幅子圖,它含有圖中所有頂點且是一棵樹。
當且僅當一幅含有V個結點的圖G滿足下列五個條件之一時,他就是一棵樹:
1 G有V-1條邊且不含有環。
2 G有V-1條邊且是連通的。
3 G是連通的,且刪除任意一條邊都會使它不再連通。
4 G是無環圖,但新增任意一條邊都會產生一條環。
5 G中的任意一對頂點之間僅存在一條簡單路徑。
深度優先搜尋(DFS)的思想:
以圖的某個頂點V開始,訪問V的鄰接頂點w1,再訪問w1的鄰接頂點n1,直到當前所訪問的頂點的所有鄰接頂點都被訪問過了,然後回退到最近被訪問的頂點,如果該頂點還有未被訪問的點,則從改點繼續搜尋,否則繼續回退,直到回退到v。
深度優先搜尋中每條邊都會被訪問兩次,且第二次訪問時總會發現這個頂點已經被訪問過。
此處使用鄰接表表示圖,
C++程式碼實現如下:
上面的程式碼是假設從給定頂點可以訪問到圖的所有其他頂點。如果沒有這個假設,為了對圖作一個完整的深度優先遍歷,我們需要對每個頂點呼叫DFSUtil()。當然那之前需要先檢查頂點是否已經訪問過。//DFS.cpp //有向圖 #include <iostream> #include <list> using namespace std; class Graph { int count = 0;//頂點數 list<int> *adj; //鄰接表 void DFSUtil(int v, bool visited[]); public: void addEdge(int v, int w); //向圖中新增邊 void DFS(int v); //深度優先搜尋函式介面 Graph(int count); }; Graph::Graph(int count) { this->count = count; adj = new list<int>[count]; } void Graph::addEdge(int v, int w) { adj[v].push_back(w); } void Graph::DFSUtil(int v, bool visited[]) { visited[v] = true; cout << v << " "; for(int w:adj[v]) { if (!visited[w]) DFSUtil(w, visited); } } void Graph::DFS(int v) { bool *visited = new bool[count]; for (int i = 0; i < count; ++i) visited[i] = false; DFSUtil(v, visited); } /* 測試 */ int main() { Graph g(4); g.addEdge(0, 1); g.addEdge(0, 2); g.addEdge(1, 2); g.addEdge(2, 0); g.addEdge(2, 3); g.addEdge(3, 3); cout << "從2開始深度搜索" << endl; g.DFS(2); cout << endl; return 0; }
對於無向圖的深度優先搜尋,只是鄰接表不一樣,其他的都是一樣的。我們只需要修改addEdge(v,
w)函式:
void Graph::addEdge(int v, int w) { adj[v].push_back(w); // 將w加到v的list adj[w].push_back(v); }