【数据结构】图的深度优先搜索
圖的深度優(yōu)先搜索類似于樹的深度優(yōu)先搜索。不同的是,圖中可能包括循環(huán),即我們有可能重復(fù)訪問節(jié)點(diǎn)。為了避免訪問已經(jīng)訪問過的節(jié)點(diǎn),我們要使用一個(gè)布爾變量的數(shù)組。
例如,在下圖中,我們從節(jié)點(diǎn)2開始訪問。當(dāng)訪問到節(jié)點(diǎn)0,我們尋找它的所有緊接節(jié)點(diǎn)。節(jié)點(diǎn)2也屬于節(jié)點(diǎn)0的鄰接節(jié)點(diǎn)。如果我們沒有標(biāo)記訪問的節(jié)點(diǎn),那么節(jié)點(diǎn)2 將會(huì)被重復(fù)訪問,這樣的話整個(gè)算法過程就不會(huì)停下來了。下圖的深度優(yōu)先搜索是2,0,1,3
這種搜索算法所遵循的搜索策略是盡可能“深”地搜索一個(gè)圖。它的基本思想如下:首先訪問圖中某一起始頂點(diǎn)v,然后由v出發(fā),訪問與v鄰接且未被訪問的任一頂點(diǎn)w1,再訪問與w1鄰接且未被訪問的任一頂點(diǎn)w2,......重復(fù)上述過程。當(dāng)不能再繼續(xù)向下訪問時(shí),一次退回到最近被訪問的頂點(diǎn),若它還有鄰接頂點(diǎn)未被訪問過,則從該點(diǎn)開始繼續(xù)上述搜索過程,直到圖中所有頂點(diǎn)均被訪問過為止。
舉個(gè)例子:
上圖一幅無向圖。我們從A點(diǎn)開始遍歷,并假設(shè)左邊的節(jié)點(diǎn)先被訪問到。那么訪問順序是A,搜索A所有可訪問的鄰接節(jié)點(diǎn)并選擇B,然后訪問B,搜索B所有可訪問的鄰接節(jié)點(diǎn)并選擇D,然后訪問D,搜索D的所有可訪問的鄰接節(jié)點(diǎn)。由于D只有一個(gè)鄰接節(jié)點(diǎn)B,而B已經(jīng)被訪問過。所以回退到D的上級B(注意,不是訪問B,僅僅是回到上級)。然后再搜索B的所有可訪問的鄰接節(jié)點(diǎn),AD已經(jīng)被訪問過,所以訪問F。這個(gè)過程一直持續(xù)直到訪問過所有的節(jié)點(diǎn)。
選擇可訪問鄰接節(jié)點(diǎn)的時(shí)候,可以使用我們自己定義的順序。比如訪問A的鄰接節(jié)點(diǎn)的時(shí)候,可以先訪問B,也可以先訪問E。可根據(jù)需求靈活調(diào)整。
?
下述代碼是深度優(yōu)先搜索的C++版本,有遞歸和迭代版本。圖的實(shí)現(xiàn)使用鄰接鏈表表示。STL的list被用來存儲(chǔ)鄰接節(jié)點(diǎn)。
#include<list> #include<iostream> using namespace std;class Graph {private:int V;list<int>* adj;void DfsUtil(int v, bool visited[]);public:Graph(int n); //No of vertices~Graph(); //Pointer to an array containing adjacency listsvoid addEdge(int v, int w); //function to add an edge to graphvoid Dfs(int s); //Dfs traversal of the vertices reachable from vvoid DfsIter(int s); };Graph::Graph(int v) {V = v;adj = new list<int>[V]; }Graph::~Graph() {delete []adj;adj = NULL; }void Graph::addEdge(int v, int w) {adj[v].push_back(w); //Add w to v's list }void Graph::Dfs(int s) {bool* visited = new bool[V];for (int i = 0; i < V; i++)visited[V] = false;DfsUtil(s, visited); }void Graph::DfsUtil(int v, bool visited[]) {//Mark the current node as the visited and print itvisited[v] = true;cout<<v<<" ";//Recur for all vertices adjacent to this vertexlist<int>::iterator i;for (i = adj[v].begin(); i != adj[v].end(); i++)if (!visited[*i])DfsUtil(*i, visited); }void Graph::DfsIter(int v) {bool* visited = new bool[V];for (int i = 0; i < V; i++)visited[i] = false;list<int> stack;stack.push_back(v);list<int>::iterator i;while (!stack.empty()) {v = stack.back();cout<<v<<" ";stack.pop_back();visited[v] = true;for(i = adj[v].begin(); i != adj[v].end(); i++)if (!visited[*i])stack.push_back(*i);} delete []visited; }int main() {// Create a graph given in the above diagramGraph 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 << "Following is Depth First Traversal (starting from vertex 2) \n";g.DfsIter(2);return 0; }?
輸出:
Following is Depth First Traversal (starting from vertex 2) 2 0 1 3?
參考資料:
1. http://www.geeksforgeeks.org/depth-first-traversal-for-a-graph/
轉(zhuǎn)載于:https://www.cnblogs.com/vincently/p/4769617.html
總結(jié)
以上是生活随笔為你收集整理的【数据结构】图的深度优先搜索的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ubuntu 安装 clangd 10.
- 下一篇: Tomcat8.0.21登录时忘记用户名