如何使用递归生成器遍历二叉树?
我正在尝试遍历一个二叉树,这个树是通过下面的代码创建的。具体来说,二叉树是一个类,并且应该包含一个迭代器,调用另一个名为inorder()的方法。这个方法应该是一个递归生成器,每次迭代时返回节点的值。我试着创建一个字典来跟踪节点,但当我尝试调用inorder()方法时,它并没有工作。是不是有什么我不知道的地方?我使用了while循环,它只创建了树的左侧节点的字典(这是一种笨拙的方法)。请帮我完成这段代码。
d=[]
# A binary tree class.
class Tree(object):
def __init__(self, label, left=None, right=None):
self.label = label
self.left = left
self.right = right
self.d=dict()
def __repr__(self, level=0, indent=" "):
s = level * indent + self.label
if self.left:
s = s + "\n" + self.left.__repr__(level + 1, indent)
if self.right:
s = s + "\n" + self.right.__repr__(level + 1, indent)
return s
def traverse(self):
if self.left:
lastLabel=self.label
self.left.traverse()
if self.right:
lastLabel=self.label
d.append(lastLabel)
self.right.traverse()
else:
d.append(self.label)
return d
def __iter__(self):
return inorder(self)
# Create a Tree from a list.
def tree(sequence):
n = len(sequence)
if n == 0:
return []
i = n / 2
return Tree(sequence[i], tree(sequence[:i]), tree(sequence[i+1:]))
# A recursive generator that generates Tree labels in in-order.
def inorder(t):
for i in range(len(d)):
yield d[i]
def test(sequence):
# Create a tree.
t = tree(sequence)
# Print the nodes of the tree in in-order.
result = []
for x in t:
result.append(x)
print x
print
result_str = ''.join(result)
# Check result
assert result_str == sequence
del d[:]
def main():
# Third test
test("0123456789")
print 'Success! All tests passed!'
if __name__ == '__main__':
main()
我又改了代码 我完成了代码,但我知道这不是遍历二叉树的最佳方法。 我在我的类中定义了一个方法-traverse(),现在返回一个有序的节点列表(最开始是无序的,所以我使用了sort()方法)。然后我在我的生成器inorder()函数中对这个列表进行了循环,以返回其中的元素。 欢迎大家对我的代码提出意见,帮助我优化。请根据这段代码中的特定树类推荐一个合适的解决方案。
2 个回答
2
我对你的想法感到非常困惑。首先,这段代码里其实没有字典,我不明白你为什么要引入这个d
全局变量。
要进行二叉树的中序遍历,你只需要按照顺序访问左边的节点、当前节点和右边的节点:
def inorder(tree):
for label in tree.left:
yield label
yield tree.label
for label in tree.right:
yield label
就这么简单。
不过,我会对你的代码做一些改进:
# Document classes and functions with docstrings instead of comments
class Tree(object):
"""A binary tree class"""
def __init__(self, label, left=None, right=None):
"""Label is the node value, left and right are Tree objects or None"""
self.label = label
self.left = left # Tree() or None
self.right = right # Tree() or None
def __repr__(self):
return 'Tree(%r, %r, %r)' % (self.label, self.left, self.right)
def __iter__(self):
# No need for a separate inorder() function
if self.left is not None:
for t in self.left:
yield t
yield self.label
if self.right is not None:
for t in self.right:
yield t
def tree(indexable):
"""Return a tree of anything sliceable"""
ilen = len(indexable)
if not ilen:
# You should be clearer about empty values
# left and right should be Tree (something with left, right, and __iter__)
# or None if there is no edge.
return None
center = ilen // 2 # floor division
return Tree(indexable[center], tree(indexable[:center]), tree(indexable[center+1:]))
def test():
seq = range(10)
t = tree(seq)
# list(t) will consume an iterable
# no need for "result = []; for x in t: result.append(x)"
assert seq == list(t)
if __name__ == '__main__':
test()
8
也许我有些理解错了,但我不太明白字典在 inorder()
里有什么用。想想一般的中序遍历是什么样的:
def inorder(t):
# Process left sub tree
# Process t
# Process right sub tree
所以在生成器的角度来看,这样写会是:
def inorder(t):
if t.left:
for elem in inorder(t.left):
yield elem
yield t
if t.right:
for elem in inorder(t.right):
yield elem