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