C++深度優(yōu)先搜索的實(shí)現(xiàn)方法
本文實(shí)例講述了圖的遍歷中深度優(yōu)先搜索的C++實(shí)現(xiàn)方法,是一種非常重要的算法,具體實(shí)現(xiàn)方法如下:
首先,圖的遍歷是指從圖中的某一個(gè)頂點(diǎn)出發(fā),按照某種搜索方法沿著圖中的邊對(duì)圖中的所有頂點(diǎn)訪問(wèn)一次且僅訪問(wèn)一次。注意到樹(shù)是一種特殊的圖,所以樹(shù)的遍歷實(shí)際上也可以看作是一種特殊的圖的遍歷。圖的遍歷主要有兩種算法:廣度優(yōu)先搜索(Breadth-First-Search)和深度優(yōu)先搜索(Depth-First-Search)。
一、深度優(yōu)先搜索(DFS)的算法思想
深度優(yōu)先搜索算法所遵循的搜索策略是盡可能“深”地搜索一個(gè)圖。它的基本思想就是:首先訪問(wèn)圖中某一起始頂點(diǎn)v,然后由v出發(fā),訪問(wèn)與v鄰接且未被訪問(wèn)的任一頂點(diǎn)w1,再訪問(wèn)與w1鄰接且未被訪問(wèn)的任一頂點(diǎn)w2,……重復(fù)上述過(guò)程。當(dāng)不能再繼續(xù)向下訪問(wèn)時(shí),依次退回到最近被訪問(wèn)的頂點(diǎn),若它還有鄰接頂點(diǎn)未被訪問(wèn)過(guò),則從該點(diǎn)開(kāi)始繼續(xù)上述搜索過(guò)程,直到圖中所有頂點(diǎn)均被訪問(wèn)過(guò)為止。

如上圖所示,從頂點(diǎn)2開(kāi)始深度優(yōu)先遍歷圖,結(jié)果為:2,0,1,3。
二、DFS算法實(shí)現(xiàn)
和廣度優(yōu)先搜索一樣,為了防止頂點(diǎn)被多次訪問(wèn),需要使用一個(gè)訪問(wèn)標(biāo)記數(shù)組visited[]來(lái)標(biāo)記頂點(diǎn)是否已經(jīng)被訪問(wèn)過(guò)。
這里使用鄰接表表示圖。對(duì)于一個(gè)有向圖,假設(shè)從給定頂點(diǎn)可以訪問(wèn)到圖的所有其他頂點(diǎn),則DFS遞歸算法的C++代碼實(shí)現(xiàn):
/*************************************************************************
> File Name: DFS.cpp
> Author: SongLee
************************************************************************/
#include<iostream>
#include<list>
using namespace std;
/* 圖 */
class Graph
{
int V; // 頂點(diǎn)數(shù)
list<int> *adj; // 鄰接表
void DFSUtil(int v, bool visited[]); // 從頂點(diǎn)v深度優(yōu)先遍歷
public:
Graph(int V); // 構(gòu)造函數(shù)
void addEdge(int v, int w); // 向圖中添加邊
void DFS(int v); // 從v開(kāi)始深度優(yōu)先遍歷圖
};
/* 構(gòu)造函數(shù) */
Graph::Graph(int V)
{
this->V = V;
adj = new list<int>[V];
}
/* 添加邊,構(gòu)造鄰接表 */
void Graph::addEdge(int v, int w)
{
adj[v].push_back(w); // 將w添加到v的鏈表
}
/* 從v開(kāi)始深度優(yōu)先遍歷 */
void Graph::DFSUtil(int v, bool visited[])
{
// 訪問(wèn)頂點(diǎn)v并輸出
visited[v] = true;
cout << v << " ";
list<int>::iterator i;
for(i=adj[v].begin(); i!=adj[v].end(); ++i)
if(!visited[*i]) // 若鄰接點(diǎn)尚未訪問(wèn)
DFSUtil(*i, visited); // 遞歸
}
/* 對(duì)圖進(jìn)行深度優(yōu)先遍歷,調(diào)用遞歸函數(shù)DFSUtil() */
void Graph::DFS(int v)
{
bool *visited = new bool[V];
for(int i=0; i<V; ++i)
visited[i] = false;
// 假設(shè)從給定頂點(diǎn)v可以到達(dá)圖的所有頂點(diǎn)
DFSUtil(v, visited);
}
/* 測(cè)試 */
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 << "Depth First Traversal (starting from vertex 2) \n";
g.DFS(2);
cout << endl;
return 0;
}
上面的代碼是假設(shè)從給定頂點(diǎn)可以訪問(wèn)到圖的所有其他頂點(diǎn)。如果沒(méi)有這個(gè)假設(shè),為了對(duì)圖作一個(gè)完整的深度優(yōu)先遍歷,我們需要對(duì)每個(gè)頂點(diǎn)調(diào)用DFSUtil()。當(dāng)然那之前需要先檢查頂點(diǎn)是否已經(jīng)訪問(wèn)過(guò)。所以我們只需要修改DFS()函數(shù)部分:
void Graph::DFS()
{
bool *visited = new bool[V];
for(int i=0; i<V; ++i)
visited[i] = false;
// 對(duì)每個(gè)頂點(diǎn)調(diào)用DFSUtil(),從0開(kāi)始
for(int i=0; i<V; ++i)
if(!visited[i])
DFSUtil(i, visited);
}
對(duì)于無(wú)向圖的深度優(yōu)先搜索,只是鄰接表不一樣,其他的都是一樣的。我們只需要修改addEdge(v, w)函數(shù):
void Graph::addEdge(int v, int w)
{
adj[v].push_back(w); // 將w加到v的list
adj[w].push_back(v);
}
注意:圖的鄰接矩陣表示是唯一的,但對(duì)于鄰接表來(lái)說(shuō),如果邊的輸入次序不同,生成的鄰接表也不同。因此,對(duì)于同一個(gè)圖,基于鄰接矩陣的遍歷所得到的DFS序列和BFS序列是唯一的,基于鄰接表的遍歷所得到的DFS序列和BFS序列是不唯一的。
三、DFS算法性能分析
1 . 空間復(fù)雜度
DFS算法是一個(gè)遞歸算法,需要借助一個(gè)遞歸工作棧,故它的空間復(fù)雜度為O(|V|)。
2 . 時(shí)間復(fù)雜度
當(dāng)以鄰接表存儲(chǔ)時(shí),時(shí)間復(fù)雜度為O(|V|+|E|)。
當(dāng)以鄰接矩陣存儲(chǔ)時(shí),時(shí)間復(fù)雜度為O(|V|^2)。
相關(guān)文章
Qt中QList與QLinkedList類的常用方法總結(jié)
這篇文章主要為大家詳細(xì)介紹了Qt中QList與QLinkedList類的常用方法,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Qt有一定的幫助,需要的可以參考一下2022-12-12
C++中類的成員函數(shù)及內(nèi)聯(lián)函數(shù)使用及說(shuō)明
這篇文章主要介紹了C++中類的成員函數(shù)及內(nèi)聯(lián)函數(shù)使用及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11
C++實(shí)現(xiàn)LeetCode(164.求最大間距)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(164.求最大間距),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07
OpenCV獲取圖像中直線上的數(shù)據(jù)具體流程
對(duì)圖像進(jìn)行處理時(shí),經(jīng)常會(huì)有這類需求:客戶想要提取出圖像中某條直線或者ROI區(qū)域內(nèi)的感興趣數(shù)據(jù),進(jìn)行重點(diǎn)關(guān)注,怎么操作呢,下面小編通過(guò)實(shí)例代碼介紹下OpenCV獲取圖像中直線上的數(shù)據(jù),一起看看吧2021-11-11
基于C語(yǔ)言實(shí)現(xiàn)圖書管理信息系統(tǒng)設(shè)計(jì)
這篇文章主要為大家詳細(xì)介紹了基于C語(yǔ)言實(shí)現(xiàn)圖書管理信息系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01
C語(yǔ)言中的字符串?dāng)?shù)據(jù)在C中的存儲(chǔ)方式
這篇文章主要介紹了C語(yǔ)言中的字符串?dāng)?shù)據(jù)在C中的存儲(chǔ)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07

