In the first post, I introduced how to use Morris iteration to implement postorder traversal of a given binary tree. However it is too complicate and not easy to code during an interview. Here, I introduce another two ways to do a postorder traversal iteratively.
The first method is to use two stacks.
- 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.
    
    List<Integer> list = new ArrayList<Integer>();
    
    public List<Integer> postorderTraversal(TreeNode root) {
        if(root == null)
   return list; // corner case when root is null
  
  Stack<TreeNode> stack1 = new Stack<TreeNode>();
  Stack<TreeNode> stack2 = new Stack<TreeNode>();
  stack1.push(root);
  while(stack1.size() != 0) {
   TreeNode cur = stack1.pop();
   if(cur.left != null)
    stack1.push(cur.left);
   if(cur.right != null)
    stack1.push(cur.right);
   stack2.push(cur);
  }
  while(stack2.size() != 0) 
   list.add(stack2.pop().val);
  return list;
    }
Another way is just use one stack, and use a node to record the prior visited node. According to the type of the current node(leaf, nonleaf with only left or right child, nonleaf with both children) to perform differently.
- Each time we pick the top of the stack and check
- if it is a leaf node, then print it
- if it is a node with only left child, if pre = left child, then we know we have finish visiting the left child, print it; otherwise, the left child has not been visited yet, we push the current node pack and push the left child into stack
- if it is a node with only right child, similar with the prior one
- if it is a node with both children
- if pre = left child, we know we finish the left child and we need to continue with right child, so push itself and right child into stack
- if pre = right child, we know we have finished both child, print it
- else we have not visited any child, we push itself and left child into stack
- Update the pre node when we print something out
 public static void postorder(TreeNode root) {
  if(root == null)
   return ; // corner case when root is null
  
  Stack<TreeNode> stack = new Stack<TreeNode>();
  TreeNode pre = null, cur = null;
  stack.push(root);
  while(stack.size() != 0) {
   cur = stack.pop();
   if(cur.left == null && cur.right == null) {
    System.out.println(cur.val);
    pre = cur;
   }
   else if(cur.left != null && cur.right == null) {
    if(pre == cur.left) {
     System.out.println(cur.val);
     pre = cur;
    }
    else {
     stack.push(cur);
     stack.push(cur.left);
    }
   }
   else if(cur.left == null && cur.right != null) {
    if(pre == cur.right) {
     System.out.println(cur.val);
     pre = cur;
    }
    else {
     stack.push(cur);
     stack.push(cur.right);
    }
   }
   else {
    if(pre == cur.left) {
     stack.push(cur);
     stack.push(cur.right);
    }
    else if(pre == cur.right) {
     System.out.println(cur.val);
     pre = cur;
    }
    else {
     stack.push(cur);
     stack.push(cur.left);
    }
   }
  }
 }
My implementation is somehow redundant. Here is a better implementation but a little harder to understand.http://leetcode.com/2010/10/binary-tree-post-order-traversal.html
 
没有评论:
发表评论