C++ 非递归后序图遍历?

C++ 非递归后序图遍历?,c++,recursion,tree,iteration,graph-theory,C++,Recursion,Tree,Iteration,Graph Theory,我正在寻找一些伪代码、算法或指南,它们将帮助我为广义图数据结构找到合适的迭代后序遍历算法 我发现了大量的资源(如两堆栈或一堆栈算法),它们可以很好地处理树,但对于图来说,它们无法处理循环/后边缘、交叉边缘等 我已经成功地编写了递归后序图遍历算法,如下所示: template<typename V, typename E> void tGraph<V, E>::RecursivePostOrderSearch(const tGraph& g, const Verte

我正在寻找一些伪代码、算法或指南,它们将帮助我为广义图数据结构找到合适的迭代后序遍历算法

我发现了大量的资源(如两堆栈或一堆栈算法),它们可以很好地处理树,但对于图来说,它们无法处理循环/后边缘、交叉边缘等

我已经成功地编写了递归后序图遍历算法,如下所示:

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;
}
模板
void tGraph::RecursivePostOrderSearch(常量tGraph&g、常量VertexType&u、std::set&visted、std::vector&result)
{
if(visted.find(u)=visted.end())
{
插入(u);
EdgeSet edgesOut=g.伸出量(u);
对于(类型名EdgeSet::const_迭代器iter=EdgeOut.begin();iter!=EdgeOut.end();iter++)
{
递归PostOrderSearch(g,iter->second.second,已访问,结果);
}
结果:推回(u);
}
}
模板std::vector tGraph::postOrderList(const VertexType&v)const
{
std::访问的集合;
std::向量结果;
递归PostOrderSearch(*this,v,visted,result);
返回结果;
}
其中,
V
是节点类型,
E
是边缘类型——一对“权重”和传入/传出节点对

如果我在下图上运行
::postOrderList
(根节点
A
):

我希望按此顺序获得以下节点(边按其权重的顺序排列):

  • D
    E
    F
    B
    G
    C
    A
…我上面的递归算法确实提供了正确的结果

然而,试图将其转换为一个迭代算法对我来说是一个挑战,而且我在这方面没有任何成功。我尝试过转换为尾部递归,这样我就可以转换为迭代,但我想不出来。我还尝试转换基于树的两堆栈和一堆栈算法,但也无法在那里正确复制结果

我看到过类似的堆栈溢出问题,但没有一个涉及到实际的迭代算法、伪代码,或者这种算法的递归到迭代转换,所以我相信在这个方向上的任何指导都会很有帮助


提前感谢。

结果有问题,但可以通过处理每个节点两次来处理。请使用标志指定是要访问子节点还是要将其推回

要实现这一点,您可以使用堆栈/向量以及包含“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));
        }
     }
}
模板
void tGraph::PostOrderSearch(const tGraph&g、const VertexType&u、std::set&visted、std::vector&result)
{
std::向量堆栈;
stack.push_back(std::pair(u,false));
对于(;;){
if(stack.empty())返回;//完成。
std::pair item=stack.back();
stack.pop_back();
VertexType u=项目优先;
如果(第二项){
//访问后
结果:推回(u);
}
else if(visted.find(u)=visted.end()){
//由于堆栈原因,按相反顺序添加
插入(u);
EdgeSet edgesOut=g.伸出量(u);
stack.push_back(std::pair(u,true));
对于(类型名称EdgeSet::const_reverse_iterator iter=edgesOut.rbegin();iter!=edgesOut.rend();iter++)
{
stack.push_back(std::pair(iter->second.second,false));
}
}
}

非常感谢。这很有效;我想我知道我错在哪里了。在解决这个问题的尝试中,我尝试使用
std::set
来标记节点,类似于我对
访问的
集所做的操作。但是,我没有想到最好用bool标记节点,将其推到堆栈上,然后处理bool作为一种操作码——现在我看到你是如何实现它的,这就更有意义了。再次感谢你。我真的很感谢你的帮助。