圖的廣度優先遍歷和最短路徑

1.廣度優先遍歷的過程

思想:先遍歷當前結點的全部鄰接結點,然後依次遍歷相鄰結點的全部相鄰結點

做法:使用隊列

將0結點加入到隊列中,將0從隊列取出

將0結點還未遍歷到的相鄰結點入隊

將1結點從隊列取出,將1結點還未遍歷到的相鄰結點入隊(此時沒有)

將2結點從隊列取出,將2結點還未遍歷到的相鄰結點入隊(此時沒有)

將5結點從隊列取出,將5結點還未遍歷到的相鄰結點入隊:3,4

將6結點從隊列取出,將6結點還未遍歷到的相鄰結點入隊(此時沒有)

將3結點從隊列取出,將3結點還未遍歷到的相鄰結點入隊(此時沒有)

將4結點從隊列取出,將4結點還未遍歷到的相鄰結點入隊(此時沒有)

直到隊列爲空,遍歷完成

注意:加入隊列時就要標記結點訪問過了

2.計算最短路徑

可以使用這種方式求出每個結點距離起始點的最短距離,並且計算出最短路徑

廣度優先遍歷可以求而出無權圖的最短路徑,有向圖和無向圖都同樣適用

圖的廣度優先遍歷的時間複雜度:鄰接表-O(V+E) 鄰接矩陣-O(V^2)

3.代碼實現

使用visited數組標記結點是否被訪問過
使用 from數組記錄是從哪個結點到該結點:from[3]=4 即路徑是4->3
使用ord數組記錄起始點距離遍歷到的結點的距離 

廣度優先遍歷過程:

將0結點入隊,將visited[0]設爲true

從隊列中取出頭結點v,遍歷頭結點的全部鄰接結點,將未訪問過的鄰接結點i入隊,visited[i]設爲true,from[i]=v,ord[i]=ord[v]+1

直到隊列爲空

最短路徑輸出過程:

ord[i]存儲的就是0-i結點的最短路徑

使用一個棧來存儲最短路徑,p=i, 將p入棧,不停的更新p=from[p],入棧,直到p=-1,說明到了0結點

#include<iostream>
#include<vector>
#include<queue>
#include<stack>
using namespace std;
//圖的廣度優先遍歷
class Graph{
public:
	int n;//結點數
	vector<vector<int> > g;//使用鄰接表表示一張圖
	bool directed;//是否是有向圖 
	Graph(int n,bool directed){
		this->n = n;
		this->directed = directed;
		for(int i=0; i<n; i++)
			g.push_back(vector<int>());	
	}
	//添加一條邊
	void addEdge(int v, int w)
	{
		g[v].push_back(w);
		if(!directed)
			g[w].push_back(v);
	} 	
	void print()
	{
		for(int i=0; i<n; i++)
		{
			cout<<i<<":";
			for(int j=0; j<g[i].size(); j++)
				cout<<g[i][j]<<" " ;
			cout<<endl;
		}
	} 
};
int main()
{
	int n=7;
	Graph g1(n,false);
	g1.addEdge(0,1);
	g1.addEdge(0,2);
	g1.addEdge(0,5);
	g1.addEdge(0,6);
	g1.addEdge(3,4);
	g1.addEdge(5,3);
	g1.addEdge(5,4);
	g1.addEdge(4,6);
	g1.print();
	cout<<endl;
	//廣度優先遍歷
	cout<<"廣度優先遍歷:";
	vector<bool> visited(n,false);//結點是否被訪問過
	vector<int> from(n,-1);//記錄是從哪個結點到該結點
	vector<int> ord(n,0);//記錄起始點距離遍歷到的結點的距離 
	
	queue<int> q;
	q.push(0);
	visited[0] = true;
	while(!q.empty()) {
		int v=q.front();
		q.pop(); 
		cout<<v<<" ";
		//將v結點的全部未訪問過的結點入隊 
		for(int i=0; i<g1.g[v].size(); i++)
		{
			if(!visited[g1.g[v][i]])//將未被遍歷過的結點入隊 
			{
				q.push(g1.g[v][i]);
				visited[g1.g[v][i]] = true;
				from[g1.g[v][i]] = v;
				ord[g1.g[v][i]] = ord[v]+1;
			}
		}
	}
	
	//顯示最短路徑
	//0-4
	cout<<endl<<"0-4的最短路徑長度爲"<<ord[4]<<endl;
	stack<int> s;
	int p=4;
	while(p!=-1)
	{
		s.push(p);
		p=from[p];	
	} 
	while(!s.empty())
	{
		int v = s.top();
		s.pop();
		if(s.empty())
			cout<<v;
		else
			cout<<v<<"->";	
	}
	return 0;
} 

 

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