We have seen inorder and preorder traversal, but post order traversal is slightly more complex, as we have to take care of root after both left and right subtree. Postorder traversal is also non-tail recursive ( The statements execute after the recursive call).
Also, observe that postorder traversal is just reverse of preorder traversal. Lets look at example 2 above:
Pre-order traversal, processing left child first and then right - 1, 2, 4, 5, 3, 6, 7
Pre-order traversal, processing right child first and then left - 1, 3, 7, 6, 2, 5, 4
Post-order traversal - 4, 5, 2, 6, 7, 3, 1
So idea is follow the same technique as preorder traversal and instead of adding the answer to list, we just push it to another stack.
At the end just pop all the items from the second Stack and add them to list automatically in Last in first out (LIFO) order.
The key to to iterative postorder traversal is the following:
The order of “Postorder” is: left child -> right child -> parent node.
Find the relation between the previously visited node and the current node
Use a stack to track nodes
As we go down the tree to the left, check the previously visited node. If the current node is the left or right child of the previous node, then keep going down the tree, and add left/right node to stack when applicable. When there is no children for current node, i.e., the current node is a leaf, pop it from the stack. Then the previous node become to be under the current node for next loop. You can using an example to walk through the code.
publicclassSolution {
public ArrayList <Integer>postorderTraversal(TreeNode root) {
ArrayList <Integer> lst =new ArrayList <Integer> ();
if (root ==null) {
return lst;
}
Stack <TreeNode> stack =new Stack <TreeNode> ();
stack.push(root);
TreeNode prev =null;
while (!stack.empty()) {
TreeNode curr = stack.peek();
// go down the tree.//check if current node is leaf, if so, process it and pop stack,//otherwise, keep going downif (prev ==null|| prev.left== curr || prev.right== curr) {
//prev == null is the situation for the root nodeif (curr.left!=null) {
stack.push(curr.left);
} elseif (curr.right!=null) {
stack.push(curr.right);
} else {
stack.pop();
lst.add(curr.val);
}
//go up the tree from left node//need to check if there is a right child//if yes, push it to stack//otherwise, process parent and pop stack } elseif (curr.left== prev) {
if (curr.right!=null) {
stack.push(curr.right);
} else {
stack.pop();
lst.add(curr.val);
}
//go up the tree from right node//after coming back from right node, process parent node and pop stack. } elseif (curr.right== prev) {
stack.pop();
lst.add(curr.val);
}
prev = curr;
}
return lst;
}
}
Simpler code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public List<Integer>postorderTraversal(TreeNode root) {
LinkedList<Integer> ans =new LinkedList<>();
Stack<TreeNode> stack =new Stack<>();
if (root ==null) return ans;
stack.push(root);
while (!stack.isEmpty()) {
TreeNode cur = stack.pop();
ans.addFirst(cur.val);
if (cur.left!=null) {
stack.push(cur.left);
}
if (cur.right!=null) {
stack.push(cur.right);
}
}
return ans;
}