十二、圖的遍歷--(2)深度優先搜索算法

摘自計蒜客: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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章