LeetCode - Binary Tree Postorder Traversal | Darren's Blog


http://leetcode.com/2010/10/binary-tree-post-order-traversal.html
Given a binary tree, return the postorder traversal of its nodes' values.
For the iterative and Morris Traversal ones, things become a bit complicated.


Solution:
We use a prev variable to keep track of the previously-traversed node. Let’s assume curr is the current node that’s on top of the stack. When prev is curr‘s parent, we are traversing down the tree. In this case, we try to traverse to curr‘s left child if available (ie, push left child to the stack). If it is not available, we look at curr‘s right child. If both left and right child do not exist (ie, curr is a leaf node), we print curr‘s value and pop it off the stack.

If prev is curr‘s left child, we are traversing up the tree from the left. We look at curr‘s right child. If it is available, then traverse down the right child (ie, push right child to the stack), otherwise print curr‘s value and pop it off the stack.

If prev is curr‘s right child, we are traversing up the tree from the right. In this case, we print curr‘s value and pop it off the stack.
void postOrderTraversalIterative(BinaryTree *root) {
  if (!root) return;
  stack<BinaryTree*> s;
  s.push(root);
  BinaryTree *prev = NULL;
  while (!s.empty()) {
    BinaryTree *curr = s.top();
    // we are traversing down the tree
    if (!prev || prev->left == curr || prev->right == curr) {
      if (curr->left) {
        s.push(curr->left);
      } else if (curr->right) {
        s.push(curr->right);
      } else {
        cout << curr->data << " ";
        s.pop();
      }
    }
    // we are traversing up the tree from the left
    else if (curr->left == prev) {
      if (curr->right) {
        s.push(curr->right);
      } else {
        cout << curr->data << " ";
        s.pop();
      }
    }
    // we are traversing up the tree from the right
    else if (curr->right == prev) {
      cout << curr->data << " ";
      s.pop();
    }
    prev = curr;  // record previously traversed node
  }
}

void postOrderTraversalIterative(BinaryTree *root) {
  if (!root) return;
  stack<BinaryTree*> s;
  s.push(root);
  BinaryTree *prev = NULL;
  while (!s.empty()) {
    BinaryTree *curr = s.top();
    if (!prev || prev->left == curr || prev->right == curr) {
      if (curr->left)
        s.push(curr->left);
      else if (curr->right)
        s.push(curr->right);
    } else if (curr->left == prev) {
      if (curr->right)
        s.push(curr->right);
    } else {
      cout << curr->data << " ";
      s.pop();
    }
    prev = curr;
  }
}
Iterative Version
http://codesniper.blogspot.com/2015/04/145-binary-tree-postorder-traversal.html
we have to push both left and right to stack. Obviously, if current node's left is not null, we push its left, if cur's right is not null, we have to check if the cur'right has been processed, if so, output cur.
    public List<Integer> postorderTraversal(TreeNode root) {  
    List<Integer> res=new ArrayList<Integer>();  
    if(root==null) return res;  
    Stack<TreeNode> st=new Stack<TreeNode>();  
    TreeNode pre=null;  
    while(root!=null || !st.isEmpty()){  
      if(root!=null){  
        st.push(root);  
        root=root.left;  
      }  
      else{  
        if(st.peek().right==null || st.peek().right==pre){  
          pre=st.pop();  
          res.add(pre.val);  
        }  
        else { root=st.peek().right; }
      }  
    }  
http://yucoding.blogspot.com/2013/12/leetcode-question-binary-tree-postorder.html
(1) Push the root node into the stack.
(2) while the stack is not empty, do:
       if 
          the top node is a leaf node (no left&right children), pop it.
          or if the top node has been visited, pop it. (here we use a sign head to show the latest popped node, if the top node's child = the latest popped node, either left or right, it must has been visited.)
       else
          b. push the right child of the top node (if exists)
          c. push the left child of the top node (if exists)
    vector<int> postorderTraversal(TreeNode *root) {
        stack<TreeNode*> st;
        vector<int> res;
        if (!root){return res;}
        st.push(root);
        TreeNode* head=root;
        while (!st.empty()){
            TreeNode* top = st.top();
            if ((top->left==NULL && top->right==NULL)||top->right==head || top->left==head){
                res.push_back(top->val);
                st.pop();
                head = top;
            }else{
                if (top->right!=NULL){st.push(top->right);}
                if (top->left!=NULL){st.push(top->left);}
            }
        }
        return res;
    }
EPI BinaryTreePostorderTraversalIterative.java
invertedPreOrderTraversal BinaryTreePostorderTraversalIterativeAlternative.java
http://blog.csdn.net/linhuanmars/article/details/22009351
http://www.danielbit.com/blog/puzzle/leetcode/leetcode-binary-tree-postorder-traversal
Alternative Solution: Using Two Stacks, print post-order reversely first: O(n) space
The order of traversal is a node, then its right child followed by its left child. This yields post-order traversal in reversed order. Using a second stack, we could reverse it back to the correct order.
Push the root node to the first stack.
Pop a node from the first stack, and push it to the second stack.
Then push its left child followed by its right child to the first stack.
Repeat step 2) and 3) until the first stack is empty.
Once done, the second stack would have all the nodes ready to be traversed in post-order. Pop off the nodes from the second stack one by one and you’re done.
void postOrderTraversalIterativeTwoStacks(BinaryTree *root) {
  if (!root) return;
  stack<BinaryTree*> s;
  stack<BinaryTree*> output;
  s.push(root);
  while (!s.empty()) {
    BinaryTree *curr = s.top();
    output.push(curr);
    s.pop();
    if (curr->left)
      s.push(curr->left);
    if (curr->right)
      s.push(curr->right);
  }
  while (!output.empty()) {
    cout << output.top()->data << " ";
    output.pop();
  }
}

If you keep visited flags in the binary tree while traversing, the problem could be solved in a more direct manner. 


We use a prev variable to keep track of the previously-traversed node. Let’s assume curr is the current node that’s on top of the stack. When prev is curr‘s parent, we are traversing down the tree. In this case, we try to traverse to curr‘s left child if available (ie, push left child to the stack). If it is not available, we look at curr‘s right child. If both left and right child do not exist (ie, curr is a leaf node), we print curr‘s value and pop it off the stack.
If prev is curr‘s left child, we are traversing up the tree from the left. We look at curr‘s right child. If it is available, then traverse down the right child (ie, push right child to the stack), otherwise print curr‘s value and pop it off the stack.
If prev is curr‘s right child, we are traversing up the tree from the right. In this case, we print curr‘s value and pop it off the stack. - O(h) space

void postOrderTraversalIterative(BinaryTree *root) {

  if (!root) return;

  stack<BinaryTree*> s;

  s.push(root);

  BinaryTree *prev = NULL;

  while (!s.empty()) {

    BinaryTree *curr = s.top();
    // we are traversing down the tree
    if (!prev || prev->left == curr || prev->right == curr) {
      if (curr->left) {
        s.push(curr->left);
      } else if (curr->right) {
        s.push(curr->right);
      } else {
        cout << curr->data << " ";
        s.pop();
      }
    }
    // we are traversing up the tree from the left
    else if (curr->left == prev) {
      if (curr->right) {
        s.push(curr->right);
      } else {
        cout << curr->data << " ";
        s.pop();
      }
    }
    // we are traversing up the tree from the right
    else if (curr->right == prev) {
      cout << curr->data << " ";
      s.pop();
    }
    prev = curr;  // record previously traversed node
  }
}

The above method is easy to follow, but has some redundant code.

void postOrderTraversalIterative(BinaryTree *root) {

  if (!root) return;

  stack<BinaryTree*> s;

  s.push(root);

  BinaryTree *prev = NULL;

  while (!s.empty()) {

    BinaryTree *curr = s.top();
    if (!prev || prev->left == curr || prev->right == curr) {
      if (curr->left)
        s.push(curr->left);
      else if (curr->right)
        s.push(curr->right);
    } else if (curr->left == prev) {
      if (curr->right)
        s.push(curr->right);
    } else {
      cout << curr->data << " ";
      s.pop();
    }
    prev = curr;
  }
}
public ArrayList<Integer> postorderTraversal(TreeNode root) {
        ArrayList<Integer> result = new ArrayList<Integer>();
        if (root == null)
            return result;
        Deque<TreeNode> stack = new ArrayDeque<TreeNode>();     // Used to restore parents
        stack.push(root);
        TreeNode q = null;
        while (!stack.isEmpty()) {
            TreeNode p = stack.peek();
            if (q == null || p == q.left || p == q.right) { // Traverse downwards
                if (p.left == null && p.right == null) {    // Current node is a leaf; access it
                    result.add(p.val);
                    stack.pop();
                } else {        // Current node is not a leaf; consider its left child if any, or its right child
                    if (p.left != null)
                        stack.push(p.left);
                    else
                        stack.push(p.right);
                }
            } else if (p.left == q) {   // Traverse backwards, and previous node is current node's left child
                if (p.right == null) {  // Current node has no right child; access it
                    result.add(p.val);
                    stack.pop();
                } else {        // Current node has right child; consider the right child
                    stack.push(p.right);
                }
            } else {        // Traverse backwards, and previous node is current node's right child; access it
                result.add(p.val);
                stack.pop();
            }
            q = p;
        }
        return result;
    }
http://rleetcode.blogspot.com/2014/06/binary-tree-postorder-traversal.html
we can ' push left child from root until left most leaf into stack. then start pop node  from the stack, however, if the current node which going to be pop out has right node we should start push all left nodes of the right child until to leaf. 
public List<Integer> postorderTraversal(TreeNode root) {
ArrayList<Integer> result = new ArrayList<Integer>();
if (root == null){
return result;
}
Stack<TreeNode> stack =new Stack<TreeNode> ();
LinkedList<TreeNode> visitedList= new LinkedList<TreeNode> ();
while(root!=null){
stack.push(root);
root=root.left;
}
while(!stack.isEmpty()){
TreeNode current = stack.peek();
if (current.right == null || visitedList.contains(current)){
result.add(current.val);
stack.pop();
if (visitedList.contains(current)){
visitedList.remove(current);
}
}
else{
visitedList.add(current);
root=current.right;
while (root!=null){
stack.push(root);
root=root.left;
}
}
}
return result;
}
Using Visited Hashset:
http://leetcode0.blogspot.com/2013/11/binary-tree-postorder-traversal.html
    public List<Integer> postorderTraversal(TreeNode root) {
         List<Integer> result = new LinkedList();
         if(root ==null)
            return result;
         Stack<TreeNode> stack = new Stack();
         Set<TreeNode> set = new HashSet();
         stack.push(root);
         set.add(root);
         while(!stack.isEmpty()){
             TreeNode node = stack.pop();
             if(set.contains(node)){// first time to find this node
                stack.push(node);
                if(node.right!=null){
                    stack.push(node.right);
                    set.add(node.right);
                }
                if(node.left!=null){
                    stack.push(node.left);
                    set.add(node.left);
                }
                 set.remove(node);
             }else{// node should be printed directly
                 result.add(node.val);
             }
         }// end of while
         return result;
    }

public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> result=new ArrayList<Integer>();
if (root==null){
return result;
}
Stack<TreeNode> stack=new Stack<TreeNode>();
TreeNode runner=root;
while (runner!=null){
stack.push(runner);
runner=runner.left;
}
// child node used to record if mid node's child has been visited inorder to tell if need to pop out
//the mid node
TreeNode child=null;
while (!stack.isEmpty()){
TreeNode current=stack.peek();
if (current.right==null || current.right==child){
result.add(stack.pop().val);
// catch the child node, inorder mid node could check if its child already be visited
child=current;
}
else{
current=current.right;
while (current!=null){
stack.push(current);
current=current.left;
}
}
}
return result;
}

http://en.wikipedia.org/wiki/Tree_traversal#Post-order_2
iterativePostorder(node)
  parentStack = empty stack  
  lastnodevisited = null 
  while (not parentStack.isEmpty() or node ≠ null)
    if (node ≠ null)
      parentStack.push(node)
      node = node.left
    else
      peeknode = parentStack.peek()
      if (peeknode.right ≠ null and lastnodevisited ≠ peeknode.right) 
        /* if right child exists AND traversing node from left child, move right */
        node = peeknode.right
      else
        parentStack.pop() 
        visit(peeknode)
        lastnodevisited = peeknode
Morris Traversal
public ArrayList<Integer> postorderTraversal(TreeNode root) {
        ArrayList<Integer> result = new ArrayList<Integer>();
        TreeNode dummy = new TreeNode(0);
        dummy.left = root;
        TreeNode p = dummy, q = null;
        while (p != null) {
            if (p.left == null) {
                p = p.right;
            } else {
                // Find in-order predecessor of current node
                q = p.left;
                while (q.right != null && q.right != p)
                    q = q.right;
                if (q.right == null) {    // Its left subtree has not been traversed; link it to its predecessor
                    q.right = p;
                    p = p.left;
                } else {
                    // Its left subtree has been traversed; add the numbers from p's left child to its in-order
                    // predecessor in reverse order, and recover tree structure
                    reverse(p.left, q);
                    TreeNode temp = q;
                    while (temp != p.left) {
                        result.add(temp.val);
                        temp = temp.right;
                    }
                    result.add(temp.val);
                    reverse(q, p.left);
                    q.right = null;
                    p = p.right;
                }
            }
        }
        return result;
    }
    private void reverse(TreeNode from, TreeNode to) {
        if (from == to)
            return;
        TreeNode q = from, p = from.right;
        while (q != to) {
            TreeNode next = p.right;
            p.right = q;
            q = p;
            p = next;
        }
    }

Recursive Version
    public ArrayList<Integer> postorderTraversal(TreeNode root) {
        ArrayList<Integer> result = new ArrayList<Integer>();
        recursivePreorderTraversal(root, result);
        return result;
    }
    private void recursivePreorderTraversal(TreeNode root, ArrayList<Integer> result) {
        if (root == null)
            return;
        recursivePreorderTraversal(root.left, result);  // Traverse the left subtree
        recursivePreorderTraversal(root.right, result); // Traverse the right subtree
        result.add(root.val);   // Access the value of current node
    }

From http://leetcode.com/2010/10/binary-tree-post-order-traversal.html
Post-order traversal is useful in some types of tree operations:
Tree deletion. In order to free up allocated memory of all nodes in a tree, the nodes must be deleted in the order where the current node can only be deleted when both of its left and right subtrees are deleted.

Evaluating post-fix notation.
If you keep visited flags in the binary tree while traversing, the problem could be solved in a more direct manner. 

Post-order traversal is useful in some types of tree operations:

Tree deletion. In order to free up allocated memory of all nodes in a tree, the nodes must be deleted in the order where the current node can only be deleted when both of its left and right subtrees are deleted.
Evaluating post-fix notation.

http://www.geeksforgeeks.org/iterative-postorder-traversal-using-stack/
The idea is to move down to leftmost node using left pointer. While moving down, push root and root’s right child to stack. Once we reach leftmost node, print it if it doesn’t have a right child. If it has a right child, then change root so that the right child is processed before.
Following is detailed algorithm.
1.1 Create an empty stack
2.1 Do following while root is not NULL
    a) Push root's right child and then root to stack.
    b) Set root as root's left child.
2.2 Pop an item from stack and set it as root.
    a) If the popped item has a right child and the right child 
       is at top of stack, then remove the right child from stack,
       push the root back and set root as root's right child.
    b) Else print root's data and set root as NULL.
2.3 Repeat steps 2.1 and 2.2 while stack is not empty.
    static Node root;
    ArrayList<Integer> list = new ArrayList<Integer>();
 
    // An iterative function to do postorder traversal of a given binary tree
    ArrayList<Integer> postOrderIterative(Node node) {
        Stack<Node> S = new Stack<Node>();
         
        // Check for empty tree
        if (node == null) {
            return list;
        }
        S.push(node);
        Node prev = null;
        while (!S.isEmpty()) {
            Node current = S.peek();
 
            /* go down the tree in search of a leaf an if so process it and pop
            stack otherwise move down */
            if (prev == null || prev.left == current || prev.right == current) {
                if (current.left != null) {
                    S.push(current.left);
                } else if (current.right != null) {
                    S.push(current.right);
                } else {
                    S.pop();
                    list.add(current.data);
                }
 
                /* go up the tree from left node, if the child is right
                push it onto stack otherwise process parent and pop stack */
            } else if (current.left == prev) {
                if (current.right != null) {
                    S.push(current.right);
                } else {
                    S.pop();
                    list.add(current.data);
                }
                 
                /* go up the tree from right node and after coming back
                 from right node process parent and pop stack */
            } else if (current.right == prev) {
                S.pop();
                list.add(current.data);
            }
 
            prev = current;
        }
 
        return list;
    }
Read full article from LeetCode - Binary Tree Postorder Traversal | Darren's Blog

Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts