简体   繁体   中英

PostOrder Traversal using one stack

I am trying the get my head around understanding DFS tree traversals using stack. I find it quite intuitive in converting a recursive solution to an iterative one for preorder traversal. However, I find it hardly difficult to understand postorder traversal using this link. https://www.geeksforgeeks.org/iterative-postorder-traversal-using-stack/ . Is there an intuitive and simpler way of thinking about this? Preorder code:

void iterativePreorder(node *root)
{
    // Base Case
    if (root == NULL)
       return;

    // Create an empty stack and push root to it
    stack<node *> nodeStack;
    nodeStack.push(root);

    /* Pop all items one by one. Do following for every popped item
       a) print it
       b) push its right child
       c) push its left child
    Note that right child is pushed first so that left is processed first */
    while (nodeStack.empty() == false)
    {
        // Pop the top item from stack and print it
        struct node *node = nodeStack.top();
        printf ("%d ", node->data);
        nodeStack.pop();

        // Push right and left children of the popped node to stack
        if (node->right)
            nodeStack.push(node->right);
        if (node->left)
            nodeStack.push(node->left);
    }
}

With pre-order traversal, the code

  • displays the data for the current node
  • traverses the left subtree
  • traverses the right subtree

With post-order traversal, the code

  • traverses the left subtree
  • traverses the right subtree
  • displays the data for the current node

So the difference is that the data needs to be stored on the stack when performing post-order traversal, so that it can be printed last. There are a couple of different ways to accomplish this. One way is to change the stack implementation to distinguish between child pointers and data pointers.

When a child pointer is popped, the actions are

  • push the current node as a data pointer
  • push the right node as a child pointer
  • push the left node as a child pointer

When a data pointer is popped, the action is

  • display the data for the node

Then the traversal is started by pushing the root node as a child pointer.

While the code is harder, iterative postorder can be more intuitive than the other traversals because the others have been refactored while this one can't be similarly refactored.

Use the first solution here:https://articles.leetcode.com/binary-tree-post-order-traversal/

The intuition is that recursive functions have information that iterative methods don't, mainly the direction of traversal. When a recursive function executes or recoils, it knows where it came from by which line of code it's executing. IE if you are printing or processing the current node, you know you've already visited the children because they were called recursively already.

An iterative solution can track it by using a "previous" pointer, hence you see the checks for "if previous is not either child of current node", then it means you're traversing downward and you need to go left. The other possibilities are that the previous came from the left or right child node. Once all the cases are handled, you have a solution.

Please find below the code snippet of PostOrder Traversal using one stack in java

public class PostOrderWithoutRecurssion {

    static Stack<Node> stack = new Stack<Node>();

    static class Node{
        int data;
        int status;
        Node left, right;

        Node(int data){
            this.data = data;
            this.status=0;
        }
    }//end class Node

    public static void main(String[] args) {
        Node root = new Node(1);
        root.left = new Node(2);
        root.right = new Node(3);
        root.left.left = new Node(4);
        root.left.right = new Node(5);
        root.right.left = new Node(6);
        root.right.right = new Node(7);
        root.left.left.left = new Node(8);
        root.left.left.right = new Node(9);

        postOrderWithoutRecurssion(root);
    }//end main

    public static void postOrderWithoutRecurssion(Node root) {
        Node temp = root;

        while(temp!=null || stack.size()>0) {

            while(temp!=null) {
                temp.status = 1;
                stack.push(temp);
                temp = temp.left;
            }

            temp = stack.pop();

            if(null==temp.left && null == temp.right) {
                temp.status = 2;
                System.out.println(temp.data);
            }else if(null != temp.right) {
                if(temp.left.status==2 && temp.right.status==2) {
                    temp.status = 2;
                    System.out.println(temp.data);
                    temp = null;
                }else {
                    if(temp.status!=1) {
                        temp.status = 1;
                        stack.push(temp);
                    }else {
                        stack.push(temp);
                    }
                }
            }

            if(null!=temp) {
                temp = temp.right;    
            }

        }
    }//end postOrderWithoutRecurssion
}

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