圖的深度優先搜索(DFS)簡介與實現(遞歸與非遞歸方法)


        上一篇剛剛學習了C++圖的實現,今天對深度優先搜索(DFS)進行了一定學習,並作出一定實現。在本文中圖的實現,以及相應的函數調用(如獲得第一個鄰接頂點、獲得下一個鄰接頂點等)均是基於上文中的實現,故如果想參考測試代碼,還需導入上文中相應的類定義。關於C++圖的實現可參考此處,這里實現了對圖的鄰接表以及鄰接矩陣兩種實現,而本文的深度優先搜索對於上面兩種實現均是可行的。

        當然,對於圖的深度優先搜索的相關定義,本文也不再過多贅述,維基的解釋應該就足夠,下面將探討其實現。

        1、深度優先搜索的非遞歸實現:

         要實現非遞歸的深度優先搜索,本文用到棧s來存儲,用一個數組visited(初始所有元素為false,代表未訪問)來做訪問的標記。基本思想是:從給定的搜索的第一個頂點loc開始,將其壓入堆棧,並標記visited[loc]為true表示已訪問;之后循環進行如下操作,只要棧不為空,取出最上方元素,將其記錄(本文直接打印,若有需要,可將其存入數組or Vector),然后去打所有的鄰接頂點,只要還未訪問(visited相應值為false),就將其壓入棧,並標記為已訪問。當棧中元素為0時,算法結束時,而所有訪問過的點,均被標記過,並被壓入棧中過,只要圖是連通的,那么就做到所有點都被輸出或記錄。

        注意:剛才有提過,以上針對於連通的圖,而對於圖蟲存在不同的連通分量的情況,可以在一次while循環之后,檢查visited判斷是否所有元素都被訪問過,若存在未被訪問的點,則在選取一個點,重復以上操作即可,本文中並不對此加以實現。

        下面將在說明遞歸調用之后統一貼出示例代碼。

        2、深度優先搜索的遞歸實現:

        遞歸實現的思路則好理解的多,基於回溯的思想。對於所給的點,得到一個鄰接頂點后,繼續對該頂點深度搜索,指導找不到下一個點,在退回一步,找下一個鄰接頂點,在進行搜索。

       以下貼出代碼,結合理解。

//FileName: DFS 
//圖的深度優先遍歷 ---遞歸與非遞歸實現
#include"Graphlnk.h"
#include"Graphmtx.h"
#include<iostream>
#include<stack>
using namespace std;

template<class T ,class E>
void DFS(Graphmtx<T,E> &G, const T &v,int judge)//非遞歸算法,參數int i用以區分遞歸與非遞歸
{
	cout<<"-------非遞歸算法被調用-------"<<endl;
	stack<int> s;
	int i,loc,out,next;
	int n = G.NumberOfVertices(); //頂點數
	bool *visited = new bool[n];
	for(i = 0;i<n;i++)
		visited[i] = false;
	loc = G.getVertexPos(v);
	s.push(loc);
	visited[loc]=true; //標記
	while(!s.empty())
	{
		out = s.top();
		s.pop();
		cout<<G.getValue(out)<<" ";
		next = G.getFirstNeighbor(out); //將所有未被標記的鄰接點壓入堆棧
		while(next!=-1)
		{
			if(visited[next]==false)
			{
				s.push(next);
				visited[next] = true;
			}
			
			next = G.getNextNeighbor(out,next);
		}
	}
	delete []visited;
}
template<class T ,class E>
void DFS(Graphmtx<T,E> &G, const T &v)
//void DFS(Graphlnk<T,E> &G, const T &v)
{
	cout<<"-------遞歸算法被調用-------"<<endl;
	int i, loc, n =G.NumberOfVertices();
	bool *visited = new bool[n];
	for (i = 0;i<n;i++)
		visited[i] = false;
	loc = G.getVertexPos(v);
	DFS(G , loc , visited);
	delete []visited;
}

template<class T ,class E>
void DFS(Graphmtx<T,E> &G, int v, bool  *visited) //遞歸實現算法
//void DFS(Graphlnk<T,E> &G, int v, bool  *visited)
{
	cout<< G.getValue(v)<< " ";
	visited[v] = true;
	int w = G.getFirstNeighbor(v);
	while(w!=-1)
	{
		if(visited[w]==false)
		{	
			DFS(G, w, visited);
		}
		w = G.getNextNeighbor(v,w);		
	}
}


void test_DFS()
{
	char first;
	Graphmtx<char,int> g(30);
	//Graphlnk<char ,int> g(30);
	g.inputGraph();
	g.outputGraph();
	cout<<"輸入深度優先搜索的第一個點:"<<endl;
	cin>>first;
	//DFS(g,first);//遞歸調用
	DFS(g,first,1);//非遞歸調用
}

        注:以上代碼最后部分test_DFS()是簡單的測試程序,將其在main()直接調用即可看到效果。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM