InOrder Traversal in Python

2019-06-05 05:53发布

问题:

The problem I am tackle with is to find the first occurrence node in its inorder traversal in a BST. The code I have is given below

def Inorder_search_recursive(node,key):
    if not node:
        return None
    InOrder_search_recursive(node.lChild)
    if node.value==key:
        return node
    InOrder_search_recursive(node.rChild)

This code always return None, what's wrong with it. I think I've return node when I find a node with value k. Why cannot python pass this node???Thanks in advance

回答1:

When you call yourself recursively, like this:

InOrder_search_recursive(node.lChild)

That's just a normal function call, like any other. It just calls the function and gets back a result. It doesn't automatically return the value from that function, or do anything else.

So, you do the left-subtree search, ignore the results, then go on to check node.value == key, and, if that fails, you do the right-subtree search, again ignore the results, and fall off the end of the function, meaning you return None.

To make this work, you need to return the value you got back. But, of course, only if it's not None.

Also, you forgot to pass the key argument down to the recursive call, so you're just going to get a TypeError. (I'm guessing your real code doesn't have this problem, but since you didn't show us your real code, or a working example, I can't be sure…)

So:

def Inorder_search_recursive(node, key):
    if not node:
        return None
    result = InOrder_search_recursive(node.lChild, key)
    if result is not None:
        return result
    if node.value==key:
        return node
    return InOrder_search_recursive(node.rChild, key)

(You don't need the not None check for the right-side search, because if it returns None, we have nothing else to try and are just going to return None anyway.)



回答2:

My other answer gives the novice-friendly solution, but if you want more powerful and concise answer:

def Inorder_search_recursive_all(node, key):
    if not node:
        return
    yield from InOrder_search_recursive(node.lChild, key)
    if node.value==key:
        yield node
    yield from InOrder_search_recursive(node.rChild, key)

This generates all matches in the tree, in order. And it gives them to you as an iterator, so if you just want the first, you can stop as soon as you find one, with no wasted work:

def Inorder_search_recursive(node, key):
    return next(Inorder_search_recursive_all(node, key), None)

The tutorial section on Iterators and the following section on Generators explains most of how this works. The only missing bit is an explanation of yield from, which is explained in PEP 380.



回答3:

Since your problem is to find the first occurrence node in its inorder traversal, you should 1) traverse the tree in-order and 2) stop when you find the first occurrence.

def search(node, key):
    if node is None:
        return None
    # Search the left subtree and return early if key is found
    n = search(node.lChild, key)
    if n is not None:
        return n
    # Check middle and return early if key is found
    if node.value == key:
        return node
    # Search right subtree
    return search(node.rChild, key)