我对该图的后遍历是否正确?

时间:2020-07-04 18:42:41

标签: algorithm graph tree traversal postorder

我正在尝试实现一种需要后遍历的算法。这是我的图表(摘自here,第8页):

enter image description here

当我尝试对此进行后遍历时,我得到的顺序是:

[3, 2, 1, 5, 4, 6]

此顺序的问题是算法无法按此顺序工作。这是我用来获取它的代码(伪代码):

function PostOrder(root, out_list) {
    root.visited = true
    for child in root.Children {
        if not child.visited {
            PostOrder(child, out_list)
        }
    }
    out_list.append(root)
}

邮购是否正确?

2 个答案:

答案 0 :(得分:2)

我认为您对二叉树的后遍历感到困惑。

图中的后遍历是不同的。

图形中的后顺序 –如果我们按DFS遍历最后一次访问顶点的顺序列出这些顶点,则该顺序称为PostOrder。

假设您的根节点是6,则所提到的顺序将给出正确的答案。

请查看以下示例,了解如何生成订单遍历列表:

Pass 1:

列表:[]

6-> 5-> 1-> 2-> 3 (现在Node 3没有相邻的未访问节点)

列表:[3]

Pass 2:

6-> 5-> 1-> 2

Node 2没有相邻的未访问节点。

列表:[3,2]

第3遍:

6-> 5-> 1

Node 1没有相邻的未访问节点。

列表:[3,2,1]

第4遍:

6-> 5

Node 5没有相邻的未访问节点。

列表:[3,2,1,5]

第5遍:

6-> 4

Node 4没有相邻的未访问节点。

列表:[3、2、1、5、4]

第6遍:

Node 6没有相邻的未访问节点。

列表:[3、2、1、5、4、6]

重要说明:

  1. 当我们使用DFS时,根据邻接列表中节点的顺序,可能会有多个路径。

  2. 可能是正确的订单:

    1. [3、2、1、5、4、6]
    2. [1、3、2、4、5、6]
    3. [3、1、2、4、5、6]
    4. [1、2、3、4、5、6]

答案 1 :(得分:1)

是的,算法的后遍历是正确的。预期的输出确实与您提供的一样。

您的困惑可能来自于该图不是二叉树,甚至不是树。这是有向图。

一般而言,后序意味着您首先在第一个出站边沿之后的节点上执行后遍历遍历,然后在其下一个出站边沿之后的节点上进行...遍历,只有在遍历所有出站边之后,该节点本身就是输出。

由于在节点1处您还没有结束,并且仍然可以转到2,从那里到3,您需要在输出任何内容之前遵循这些边沿。然后才回溯。

作为参考,这是您实现的算法in python

def postorder(root, out_list, children, visited):
    visited[root] = True
    for child in children[root]:
        if not visited[child]:
            postorder(child, out_list, children, visited)
    out_list.append(root)

children = [
    [],      # dummy for node 0
    [2],     # 1
    [1,3],   # 2
    [2],     # 3
    [2,3],   # 4
    [1],     # 5
    [5,4]    # 6 
]

nodes = []
postorder(6, nodes, children, [False] * len(children))

print(nodes) # [3, 2, 1, 5, 4, 6]