简体   繁体   中英

Generator Function for inOrder traversal

I've been working on my generator functions and expressions recently, but I'm not quite sure how I would tackle this. How could I use a generator function to yield and then later print the values in order?

I built my BST using pythons list

bst = [20, [10, [5, [2, [], []], [8, [], []]], [15, [], []]], [30, [25, [22, [], []], [27, [], []]], [35, [], [37, [], []]]]]

If I were to print the inorder traversal, I have no problem. So if I were to call inorder(bst) for the following function:

def inorder(tree):
    if tree:
        inorder(tree[1])
        print (tree[0])
        inorder(tree[2])

I get this output.

2
5
8
10
15
20
22
25
27
30
35
37

I would think that a generator expression would be equally as simple

def inorder(tree):
    if tree:
        inorder(tree[1])
        yield (tree[0])
        inorder(tree[2])

The problem I'm running into is getting my main to iterate through what's yielded in the function. I thought it was supposed to be something like

test= inorder(bst)

for i in range(0,len(l)): # l is the number of items in bst
    print (next(test))

Instead of iterating over the entire functions yields, it simply stops the iterable seemingly before it starts.

    20
Traceback (most recent call last):
  File "functionGenerator.py", line 64, in <module>
    print(next(test))
StopIteration

What do I need to do to make my function generator operate correctly?

Your inorder() implementation doesn't correctly recurse. You are only printing the current top node of your tree. That's because only calling inorder(tree[1]) or inorder(tree[2]) returns a generator object, you are not iterating over those generators.

Use

def inorder(tree):
    if tree:
        yield from inorder(tree[1])
        yield tree[0]
        yield from inorder(tree[2])

The yield from expression delegates the generator to another, yielding from that sub-generator until it is done. That way you properly recurse.

If you are using an older Python release (before Python 3.3), you need to manually iterate over the recursive calls:

def inorder(tree):
    if tree:
        for sub in inorder(tree[1]):
            yield sub
        yield tree[0]
        for sub in inorder(tree[2]):
            yield sub

Next, you can just iterate over the inorder() generator:

>>> for node in inorder(bst):
...     print(node)
...
2
5
8
10
15
20
22
25
27
30
35
37

although using next() works too:

>>> tree = inorder(bst)
>>> print(next(tree))
2
>>> print(next(tree))
5

but iteration is cleaner and stops automatically once StopIteration is raised.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM