图的广度优先遍历和最短路径

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;
} 

 

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