一、介紹
尋路演算法是用來獲取兩節點之間的路勁問題,它是基於圖的深度優先遍歷而來的,在圖的遍歷過程中,每當遍歷到一個節點是,會使用一個from陣列用來記錄該節點的上一個節點,與此同時我們會使用一個棧(先進後出),將from陣列記錄的節點依次放入棧中,然後依次再從棧中取出棧頂元素將其放入一個佇列中,最後對佇列中元素依次索引出就可得到相應節點遍歷的路徑了。
例如:
我們要獲取節點0到節點6之間遍歷的路徑
使用from陣列:
使用深度優先遍歷後就會得到
from[6] = 4
from[4] = 3
from[3] = 5
from[5] = 0
from[0] = 0
然後使用棧,將其from[i]依次放入棧中,在依次取棧頂元素放入佇列中,就可得到:0,5,3,4,6
二、程式碼實現
深度優先遍歷邏輯不變
#include <vector>
#include <stack>
#include <iostream>
#include <cassert>
using namespace std;
//路徑查詢演算法
template <typename Graph>
class Path{
private:
Graph &G; // 圖的引用
int s; // 起始點
bool* visited; // 記錄dfs的過程中節點是否被訪問
int * from; // 記錄路徑, from[i]表示查詢的路徑上i的上一個節點
//圖的深度優先遍歷
void dfs(int v){
visited[v] = true;
typename Graph::adjIterator adj(G, v);
for( int i = adj.begin(); !adj.end(); i = adj.next){
if( !visited[i] ){
from[i] = v;
dfs(i);
}
}
}
public:
//建構函式,尋路演算法,尋找graph從s點到其他的路徑
Path(Graph &graph, int s):G(graph){
assert( s >= 0 && s < G.V() );
visited = new bool[G.v()];
from = new int[G.V()];
for(int i = 0; i < G.v(); i++){
visited[i] = false;
from[i] = -1;
}
this->s = s;
//尋路演算法
dfs(s);
}
~Path(){
delete[] visited;
delete[] from;
}
提供的操作:
//查詢從s到w是否有路徑
bool hasPath(int w){
assert( w >= 0 && w < G.v() );
return visited[w];
}
//查詢從s到w的路徑。存放在棧vec中
void path(int w, vector<int> &vec) {
assert(hasPath(w));
// 透過from陣列逆向查詢到從s到w的路徑, 存放到棧中
stack<int> s;
int p = w;
while (p != -1) {
s.push(p);
p = from[p];
}
//從棧中依次取出元素, 獲得順序的從s到w的路徑
vec.clear();
while (!s.empty()) {
vec.push_back(s.top());
s.pop();
}
}
// 列印出從s點到w點的路徑
void showPath(int w){
assert(hasPath(w));
vector<int>vec;
path(w, vec);
for(int i = 0; i < vec.size(); i++){
cout<<vec[i];
if(i == vec.size() - 1)
cout<<endl;
else cout<<"->";
}
}
};
本作品採用《CC 協議》,轉載必須註明作者和本文連結