我正在尝试实现一种需要后遍历的算法。这是我的图表(摘自here,第8页):
当我尝试对此进行后遍历时,我得到的顺序是:
[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)
}
邮购是否正确?
答案 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]
重要说明:
当我们使用DFS时,根据邻接列表中节点的顺序,可能会有多个路径。
可能是正确的订单:
答案 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]