圖論系列之「基於深度優先遍歷的尋路演算法 (Path) 」

ice_moss發表於2021-05-23

一、介紹

尋路演算法是用來獲取兩節點之間的路勁問題,它是基於圖的深度優先遍歷而來的,在圖的遍歷過程中,每當遍歷到一個節點是,會使用一個from陣列用來記錄該節點的上一個節點,與此同時我們會使用一個棧(先進後出),將from陣列記錄的節點依次放入棧中,然後依次再從棧中取出棧頂元素將其放入一個佇列中,最後對佇列中元素依次索引出就可得到相應節點遍歷的路徑了。
例如:
我們要獲取節點0到節點6之間遍歷的路徑
使用from陣列:
使用深度優先遍歷後就會得到
from[6] = 4
from[4] = 3
from[3] = 5
from[5] = 0
from[0] = 0
圖論系列之「基於深度優先遍歷的尋路演算法 (Path) 」
然後使用棧,將其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 協議》,轉載必須註明作者和本文連結

相關文章