【问题标题】:How to traverse a binary Tree with a recursive generator?如何使用递归生成器遍历二叉树?
【发布时间】:2025-12-02 14:50:02
【问题描述】:

我正在尝试遍历在以下代码中创建的二叉树。准确地说,二叉树是一个类,应该包括一个调用另一个函数的迭代器,即 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()- 并返回了一个节点列表 in order 现在(起初没有排序,所以我使用了 sort() 方法。)然后我做了一个在我的生成器中循环这个列表,inorder() 函数,以产生它的元素。 非常欢迎您的所有 cmets 优化代码。 请根据此代码中特定的 Tree 类推荐合适的解决方案。

【问题讨论】:

    标签: python recursion iterator generator


    【解决方案1】:

    我完全被你的想法弄糊涂了。一方面,这段代码中实际上没有任何字典,我不明白你为什么要引入d global。

    按顺序遍历二叉树所需要做的就是遍历左侧、当前标签和右侧:

    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()
    

    【讨论】:

    • 感谢您的帮助,但您建议的代码不起作用。我想通过使用生成器来实现它。并且树没有任何索引。这段代码的主要部分是我的老师创建的,我应该完成它。
    • 我包含了一个明显通过的测试。并且它不是具有索引的 tree,而是您的 tree() 函数需要一个可索引(真正可切片)序列来创建树。 __iter__ 这里是一个生成器,正如你所要求的。
    【解决方案2】:

    也许我遗漏了一些东西,但我不确定为什么字典与 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
    

    【讨论】:

    • 我试图创建一个字典来跟踪我已经产生的节点。问题是我可以检查左叶,但当节点有左叶和右叶时,右叶保持不变。