摘自計蒜客:http://www.jisuanke.com/course/35/7316
深度優先搜索(Depth-First-Search,簡稱DFS)。這是一種常見的用於遍歷或搜索樹或者圖的算法。首先來看看深度優先搜索算法的具體過程:
開始我們假設圖上所有頂點都未被訪問,選擇圖中任一頂點,開始執行以下操作:
1.訪問當前頂點V,並將頂點標記爲已訪問;
2.遍歷與頂點v相鄰的所有頂點c,然後對頂點v所有尚未被訪問的相鄰頂點c,遞歸地執行第一步操作;如果當前頂點已經沒有未訪問的相鄰頂點了,
則說明該分支搜索結束,沿通路回溯到頂點v。
3.此時如果還有相鄰頂點沒有被訪問,則從該頂點繼續開始深度優先搜索。直到所有頂點都被訪問。
從操作方法上可以看出,深度優先搜索遍歷算法,總是沿着圖的某一深度進行遍歷,儘可能深的搜索與當前相鄰的頂點---如果相鄰的頂點都已被
訪問則回溯到上一層,直至所有頂點都已被訪問。
仔細分析後我們發現,對一個連通圖進行深度優先搜索,其實是在對該圖的一個生成樹進行搜索,這裏我們把這棵生成樹稱爲深度優先搜索樹。
如下圖就是剛纔例子的一個深度優先搜索樹。
對於算法的具體實現,因深度優先搜索的優先遍歷深度更大的頂點,所以我們可以藉助棧這一數據結構來實現:
1 將要訪問的第一個頂點 v 入棧,然後首先對其進行訪問;
2 將頂點 v 出棧,依次將與頂點 v 相鄰且未被訪問的頂點 c 壓入棧中;
3 重複第一步操作,直至棧爲空。
爲了方便,我們通常以遞歸的形式實現深度優先搜索。
下面將用鄰接表實現深度優先搜索算法,並按照遍歷的順序將頂點編號逐行輸出,其中鄰接表用到的鏈表通過vector來時顯示。
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
class Graph {
private:
int n; //!< 頂點數量
vector<int> *edges; //!< 鄰接表
bool * visited;//指向一個記錄訪問過程的bool數組
public:
Graph(int input_n) {
n = input_n;
edges = new vector<int>[n];
visited = new bool[n];
memset(visited, 0, n);
}
~Graph() {
delete[] edges;
delete[] visited;
}
void insert(int x, int y) {
edges[x].push_back(y);
edges[y].push_back(x);
}
void dfs(int vertex) {
cout << vertex << endl;
visited[vertex] = true;
//此處採用C++11標準書寫
for (int adj_vertex:edges[vertex]) {
if (!visited[adj_vertex]) {
dfs(adj_vertex);
}
}
}
};
int main() {
int n, m, k;
cin >> n >> m;
Graph g(n);
for (int i = 0; i < m; ++i) {
int x, y;
cin >> x >> y;
g.insert(x, y);
}
cin >> k;
g.dfs(k);
return 0;
}