從圖中某一頂點出發訪遍圖中其余頂點,且使每一個頂點僅被訪問一次,這一過程就叫做圖的遍歷(Traversing Graph)
****注:圖的建立上一篇博客《圖的鄰接矩陣存儲實現》已經放了源代碼了,這里要運行只要按代碼加上相應的文件就能執行****
深度優先遍歷(DFS,Depth_First_Search):
從圖中某個頂點V出發,訪問此頂點,然后從V的未被訪問的鄰接點觸犯深度優先遍歷圖,直至圖中所有和V有路徑相通的頂點都被訪問到。相當於樹的前序遍歷。針對非連通圖,只要對每個連通分量分別進行深度優先遍歷,即在先前一個頂點進行一次深度優先遍歷后,若圖中尚有頂點未被訪問,則另選圖中一個未曾被訪問的頂點作起始點,重復上述過程,直至圖中所有頂點都被訪問到為止。
右圖是遞歸遍歷的過程,其實每一層都是從A結點開始搜尋滿足條件的點 |
|
|
/* DFS.h */
#ifndef __DFS_H__
#define __DFS_H__
#include"Graph.h"
namespace meihao
{
void DFS(const meihao::Graph& g,int vi,bool*& visited); //參數->圖和頂點數組中某個頂點的下標
void DFSTraversal(const meihao::Graph& g);
};
#endif
/* testMain.cpp */
#include"DFS.h"
#include<iostream>
int main()
{
meihao::Graph g("data.txt");
meihao::DFSTraversal(g);
cout<<endl;
system("pause");
}
/* data.txt */
9
A B C D E F G H I
0 1 0 0 0 1 0 0 0
1 0 1 0 0 0 1 0 1
0 1 0 1 0 0 0 0 1
0 0 1 0 1 0 1 1 1
0 0 0 1 0 1 0 1 0
1 0 0 0 1 0 1 0 0
0 1 0 1 0 1 0 1 0
0 0 0 1 1 0 1 0 0
0 1 1 1 0 0 0 0 0
|
/* DFS.cpp */
#include"DFS.h"
namespace meihao
{
//算法都是基於鄰接矩陣實現的
void DFS(const meihao::Graph& g,int vi,bool*& visited)
{
visited[vi] = true; //修改第vi個結點的訪問標記為true
cout<<g.getGraphVertexData(vi)<<" ";
for(int idx=0;idx!=g.getGraphVertexNumber();++idx)
{
if(1==g.getGraphEdgeWeight(vi,idx)&&
false==visited[idx]) //如果(vi,idx)之間存在邊(==1),並且第idx個頂點還沒有訪問過
{
DFS(g,idx,visited); //遞歸遍歷第idx個頂點
}
}
}
void DFSTraversal(const meihao::Graph& g)
{
bool* visited = new bool[g.getGraphVertexNumber()]();
for(int idx=0;idx!=g.getGraphVertexNumber();++idx)
{
visited[idx] = false; //初始化訪問標記,全部為false,表示未訪問
}
for(int idx=0;idx!=g.getGraphVertexNumber();++idx)
{
if(false==visited[idx]) //隨便選一個點,如果未訪問過,就從它開始深度優先遍歷
DFS(g,idx,visited);
}
}
};
|
廣度優先遍歷(Breadth First Search):
類似於圖的層序遍歷,
| /* BFS.h */
#ifndef __BFS_H__
#define __BFS_H__
#include"Graph.h"
namespace meihao
{
void BFSTraversal(const meihao::Graph& g);
};
#endif
/* test.cpp */
#include"BFS.h"
#include<iostream>
int main()
{
meihao::Graph g("data.txt");
meihao::BFSTraversal(g);
cout<<endl;
system("pause");
}
/* data.txt */
9
A B C D E F G H I
0 1 0 0 0 1 0 0 0
1 0 1 0 0 0 1 0 1
0 1 0 1 0 0 0 0 1
0 0 1 0 1 0 1 1 1
0 0 0 1 0 1 0 1 0
1 0 0 0 1 0 1 0 0
0 1 0 1 0 1 0 1 0
0 0 0 1 1 0 1 0 0
0 1 1 1 0 0 0 0 0
|
/* BFS.cpp */
#include"BFS.h"
#include<queue>
namespace meihao
{
void BFSTraversal(const meihao::Graph& g)
{ //廣度優先遍歷相當於層序遍歷
queue<int> rootNode; //存放圖的頂點
bool* visited = new bool[g.getGraphVertexNumber()];
for(int idx=0;idx!=g.getGraphVertexNumber();++idx)
{
visited[idx] = false;
}
for(int idx=0;idx!=g.getGraphVertexNumber();++idx)
{ //if語句可以確保如果圖中有多個連通分量,也能每個點都訪問到
if(false==visited[idx]) //如果該結點沒有訪問到
{
//訪問
cout<<g.getGraphVertexData(idx)<<" ";
visited[idx] = true;
rootNode.push(idx);
while(!rootNode.empty()) //把剛剛訪問到的結點的下一層結點訪問並入隊列
{
for(int iidx=0;iidx!=g.getGraphVertexNumber();++iidx)
{
if(1==g.getGraphEdgeWeight(rootNode.front(),iidx)&&
false==visited[iidx])
{
cout<<g.getGraphVertexData(iidx)<<" ";
visited[iidx] = true;
rootNode.push(iidx);
}
}
rootNode.pop(); //最先訪問的一個結點出隊列
}
}
}
}
};
|
兩種遍歷算法在時間復雜度上是一樣的
深度優先遍歷算法適合圖和邊都非常多,要找到合適的頂點
廣度優先遍歷算法適合不斷擴大遍歷范圍時找到相對最優
解


