Search code examples
pythonrecursiongeneratorbinary-search-tree

Using generators to perform an inorder tree traversal on a BST


So given the following:

def inorder(t):
    if t:
        inorder(t.left)
        yield t.key
        inorder(t.right)

x = [ n for n in inorder(r) ]

x only contains the root node, why?

Here's the full code; note that the BST implementation is correct, it's the inorder() implementation with generators that is somehow wrong.

class STree(object):
    def __init__(self, value):
        self.key = value
        self.left = None
        self.right = None

def insert(r, node):
    if node.key < r.key:
        if r.left is None:
            r.left = node
        else:
            insert(r.left, node)
    else:
        if r.right is None:
            r.right = node
        else:
            insert(r.right, node)

def inorder(t):
    if t:
        inorder(t.left)
        yield t.key
        inorder(t.right)


r = STree(10)
insert(r, STree(12))
insert(r, STree(5))
insert(r, STree(99))
insert(r, STree(1))

tree = [ n for n in inorder(r) ]
print tree

Solution

  • inorder(t.left) only creates the generator object, it doesn't actually run it. You need to actually yield all the values produced by each of the sub-generators, like so:

    def inorder(t):
        if t:
            yield from inorder(t.left)
            yield t.key
            yield from inorder(t.right)
    

    Note that the yield from convenience syntax was only introduced in Python 3.3 so if you're using an older version you'll have to iterate over the sub-generators explicitly:

    # Python 2
    def inorder(t):
        if t:
            for key in inorder(t.left):
                yield key
            yield t.key
            for key in inorder(t.right):
                yield key