Help me understand Inorder Traversal without using recursion

后端 未结 14 2648
别跟我提以往
别跟我提以往 2020-12-12 11:44

I am able to understand preorder traversal without using recursion, but I\'m having a hard time with inorder traversal. I just don\'t seem to get it, perhaps, because I have

相关标签:
14条回答
  • 2020-12-12 12:26

    Start with the recursive algorithm (pseudocode) :

    traverse(node):
      if node != None do:
        traverse(node.left)
        print node.value
        traverse(node.right)
      endif
    

    This is a clear case of tail recursion, so you can easily turn it into a while-loop.

    traverse(node):
      while node != None do:
        traverse(node.left)
        print node.value
        node = node.right
      endwhile
    

    You're left with a recursive call. What the recursive call does is push a new context on the stack, run the code from the beginning, then retrieve the context and keep doing what it was doing. So, you create a stack for storage, and a loop that determines, on every iteration, whether we're in a "first run" situation (non-null node) or a "returning" situation (null node, non-empty stack) and runs the appropriate code:

    traverse(node):
      stack = []
      while !empty(stack) || node != None do:
        if node != None do: // this is a normal call, recurse
          push(stack,node)
          node = node.left
        else // we are now returning: pop and print the current node
          node = pop(stack)
          print node.value
          node = node.right
        endif
      endwhile
    

    The hard thing to grasp is the "return" part: you have to determine, in your loop, whether the code you're running is in the "entering the function" situation or in the "returning from a call" situation, and you will have an if/else chain with as many cases as you have non-terminal recursions in your code.

    In this specific situation, we're using the node to keep information about the situation. Another way would be to store that in the stack itself (just like a computer does for recursion). With that technique, the code is less optimal, but easier to follow

    traverse(node):
      // entry:
      if node == NULL do return
      traverse(node.left)
      // after-left-traversal:
      print node.value
      traverse(node.right)
    
    traverse(node):
       stack = [node,'entry']
       while !empty(stack) do:
         [node,state] = pop(stack)
         switch state: 
           case 'entry': 
             if node == None do: break; // return
             push(stack,[node,'after-left-traversal']) // store return address
             push(stack,[node.left,'entry']) // recursive call
             break;
           case 'after-left-traversal': 
             print node.value;
             // tail call : no return address
             push(stack,[node.right,'entry']) // recursive call
          end
        endwhile 
    
    0 讨论(0)
  • 2020-12-12 12:28
    def print_tree_in(root):
        stack = []
        current = root
        while True:
            while current is not None:
                stack.append(current)
                current = current.getLeft();
            if not stack:
                return
            current = stack.pop()
            print current.getValue()
            while current.getRight is None and stack:
                current = stack.pop()
                print current.getValue()
            current = current.getRight();
    
    0 讨论(0)
  • 2020-12-12 12:28

    Here is an iterative Python Code for Inorder Traversal ::

    class Node:
        def __init__(self, data):
            self.data = data
            self.left = None
            self.right = None
    
    def inOrder(root):
        current = root
        s = []
        done = 0
    
        while(not done):
            if current is not None :
                s.append(current)
                current = current.left
            else :
                if (len(s)>0):
                    current = s.pop()
                    print current.data
                    current = current.right
                else :
                    done =1
    
    root = Node(1)
    root.left = Node(2)
    root.right = Node(3)
    root.left.left = Node(4)
    root.left.right = Node(5)
    
    inOrder(root)
    
    0 讨论(0)
  • 2020-12-12 12:29

    This may be helpful (Java implementation)

    public void inorderDisplay(Node root) {
        Node current = root;
        LinkedList<Node> stack = new LinkedList<>();
        while (true) {
            if (current != null) {
                stack.push(current);
                current = current.left;
            } else if (!stack.isEmpty()) {
                current = stack.poll();
                System.out.print(current.data + " ");
                current = current.right;
            } else {
                break;
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-12 12:34

    Here's an iterative C++ solution as an alternative to what @Emadpres posted:

    void inOrderTraversal(Node *n)
    {
        stack<Node *> s;
        s.push(n);
        while (!s.empty()) {
            if (n) {
                n = n->left;
            } else {
                n = s.top(); s.pop();
                cout << n->data << " ";
                n = n->right;
            }
            if (n) s.push(n);
        }
    }
    

    0 讨论(0)
  • 2020-12-12 12:34

    I think part of the problem is the use of the "prev" variable. You shouldn't have to store the previous node you should be able to maintain the state on the stack (Lifo) itself.

    From Wikipedia, the algorithm you are aiming for is:

    1. Visit the root.
    2. Traverse the left subtree
    3. Traverse the right subtree

    In pseudo code (disclaimer, I don't know Python so apologies for the Python/C++ style code below!) your algorithm would be something like:

    lifo = Lifo();
    lifo.push(rootNode);
    
    while(!lifo.empty())
    {
        node = lifo.pop();
        if(node is not None)
        {
            print node.value;
            if(node.right is not None)
            {
                lifo.push(node.right);
            }
            if(node.left is not None)
            {
                lifo.push(node.left);
            }
        }
    }
    

    For postorder traversal you simply swap the order you push the left and right subtrees onto the stack.

    0 讨论(0)
提交回复
热议问题