我正在尝试将递归和yield结合起来以有序遍历一棵树
这就是我目前所拥有的。但是,当我尝试遍历树时,似乎只遍历根节点
class Tree:
...
def post_order(self, node: TreeNode):
"""Yield next node in post order from node"""
for child in node.get_children():
self.post_order(child)
yield node
if __name__ == '__main__':
root = TreeNode('root')
depth1a = TreeNode('1a')
depth1b = TreeNode('1b')
root.add_children(depth1a, depth1b)
tree = Tree(root)
for node in tree.post_order(root):
print(node.get_element())
运行代码时,它只会打印出来
root
这是第一个节点的元素,而不是我想要的
1a
1b
root
有人知道我做错了吗?
谢谢大家
答案 0 :(得分:1)
感谢张实唯,事实证明我必须使用yield from
。调用生成器函数不会从中产生:
class Tree:
...
def post_order(self, node: TreeNode):
"""Yield next node in post order from node"""
for child in node.get_children():
yield from self.post_order(child)
yield node
答案 1 :(得分:0)
迈克·潘(Mike Pham)的回答很好,但是我想分享一种回溯方法,该方法可以帮助我们了解如何使用直接递归而不是for
循环来手动构建所需的序列。这不是一个更好的程序。这是检查您对发电机的掌握程度的一种练习-
from functools import reduce
def empty ():
yield from ()
def postorder (node, backtrack = empty(), visit = False):
if visit:
yield node.data
yield from backtrack
elif node.children:
yield from reduce \
( lambda it, child: postorder (child, it)
, node.children[::-1]
, postorder (node, backtrack, True)
)
else:
yield from postorder (node, backtrack, True)
测试一下-
class node:
def __init__ (self, data, *children):
self.data = data
self.children = children
tree = \
node("a",
node("b",
node("e"),
node("f",
node("k"))),
node("c"),
node("d",
node("g"),
node("h"),
node("i"),
node("j")))
print(list(postorder(tree)))
# [ 'e', 'k', 'f', 'b', 'c', 'g', 'h', 'i', 'j', 'd', 'a' ]
这可能有助于您了解yield
实际为您所做的事情。这是没有它的相同程序。 粗体-
def empty ():
return []
def postorder (node, backtrack = empty, visit = False):
def gen ():
if visit:
return [ node.data ] + backtrack()
elif node.children:
return reduce \
( lambda it, child: postorder (child, it)
, node.children[::-1]
, postorder (node, backtrack, True)
) ()
else:
return postorder (node, backtrack, True) ()
return gen
def run (gen):
return gen ()
print(run(postorder(tree)))
# [ 'e', 'k', 'f', 'b', 'c', 'g', 'h', 'i', 'j', 'd', 'a' ]