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