簡體   English   中英

非遞歸的后序圖遍歷?

[英]Non-recursive post-order graph traversal?

我正在尋找一些偽代碼,算法或指導,這將幫助我找到適用於廣義圖數據結構的迭代后序遍歷算法。

我發現有很多資源(比如兩個堆棧或一個堆棧算法)可以很好地處理樹木,但是因為它們無法處理循環/后邊緣,交叉邊緣等而分解圖形。

我已經成功編寫了一個遞歸的后序圖遍歷算法,如下所示:

template<typename V, typename E>
void tGraph<V, E>::RecursivePostOrderSearch(const tGraph& g, const VertexType& u, std::set<VertexType>& visited, std::vector<VertexType>& result)
{
    if (visited.find(u) == visited.end())
    {
        visited.insert(u);

        EdgeSet edgesOut = g.outgoingEdgesOf(u);

        for(typename EdgeSet::const_iterator iter = edgesOut.begin(); iter != edgesOut.end(); iter++)
        {
            RecursivePostOrderSearch(g, iter->second.second, visited, result);
        }

        result.push_back(u);
    }
}

template<typename V, typename E> std::vector<V> tGraph<V, E>::postOrderList(const VertexType& v) const
{
    std::set<V> visited;
    std::vector<V> result;

    RecursivePostOrderSearch(*this, v, visited, result);

    return result;
}

其中V是節點類型, E是邊緣類型 - “權重”對和傳入/傳出節點對。

如果我在下圖中運行::postOrderList (使用根節點A ):

有問題的無向圖

我希望按此順序獲得以下節點(邊緣按其重量順序排列):

  • DEFBGCA

...而我上面的遞歸算法確實提供了正確的結果。

然而,嘗試將其轉換為迭代算法一直是我自己的挑戰,而且我沒有取得任何成功。 我已經嘗試轉換為尾遞歸,所以我可以轉換為迭代,但我無法弄清楚。 我也嘗試轉換基於樹的雙棧和單棧算法,但也無法正確復制結果。

我已經看到類似的堆棧溢出問題,但似乎沒有一個覆蓋實際的迭代算法,偽代碼或遞歸到這種算法的迭代轉換,所以我認為在這方面的任何指導都會有所幫助。

提前致謝。

result.push_back存在問題,但可以通過處理每個節點兩次來處理,使用標志來指定是要訪問子節點還是將其推回。

要實現這一點,您可以使用包含“u”和bool(用於標志)的結構的堆棧/向量。

這些方面的東西:

template<typename V, typename E>
void tGraph<V, E>::PostOrderSearch(const tGraph& g, const VertexType& u, std::set<VertexType>& visited, std::vector<VertexType>& result)
{
    std::vector<std::pair<VertexType,bool> > stack;
    stack.push_back(std::pair<VertexType, bool>(u,false));
    for(;;) {
      if (stack.empty()) return; // Done.
      std::pair<VertexType, bool> item=stack.back();
      stack.pop_back();
      VertexType u=item.first;
      if (item.second) {
         // Post-visit
         result.push_back(u);
      }
      else if (visited.find(u)==visited.end()) {
        // Add in reverse order, due to stack
        visited.insert(u);

        EdgeSet edgesOut = g.outgoingEdgesOf(u);

        stack.push_back(std::pair<VertexType, bool>(u,true));   

        for(typename EdgeSet::const_reverse_iterator iter = edgesOut.rbegin(); iter != edgesOut.rend(); iter++)
        {
            stack.push_back(std::pair<VertexType,bool>(iter->second.second,false));
        }
     }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM