下面来讲讲迭代版本的二叉树后序遍历。
首先,我们先来造一个二叉树,先自己模拟一下后序遍历。
为了便于理解,我在之前的中序遍历的树上进行了扩展。
1.
回归一下我们之前的中序遍历,4-3-9,碰到空了就可以停了,但后序遍历是必须左,右子树都访问了,才可以。
所以,我们还要继续下去,走到6,然后6再走到4。在这里我称为一个叫leftRightMost的遍历:
即如果左子树不为空,优先走左边分支;当左子树为空,走一个右边的试试;总之,以走左边的为主。
最后,我们到了4, 4的左右子树都为空,它可以输出了。
2. 接着,我们看看栈的top = 6. 我们将6的右子树看成一棵独立的树,继续按照1中的做法,找到9这个节点,此时9可以输出了。
3. 此时top = 6, 同2步骤,我们将7的右子树看成一棵独立的树,走10,输出10.
4.关键的步骤来了,此时栈的top = 7, 此时9, 10都输出了,所以我们可以输出7 了。
5. 同样的,top = 6, top的右节点7已经输出了,所以,我们可以输出6了。
之后的步骤就是重复leftRightMost遍历,和看栈的top适不适合输出。
最后总结: 当且仅当一个节点的left, right = 空 或者,这个节点的右节点已经输出了,它才能被输出。
代码:
public List<Integer> postorderTraversal(TreeNode root) {
Stack<TreeNode> store = new Stack<>();
List<Integer> list = new ArrayList<>();
if (root == null) {
return list;
}
putLeftRightMost(store, root);
TreeNode pre = null;
while (!store.empty()) {
TreeNode cur = store.peek();
if (cur.right == null || cur.right == pre) { // only if one node has no children or his right child has been printed
pre = store.pop();
list.add(pre.val);
} else {
putLeftRightMost(store, cur.right);
}
}
return list;
}
private void putLeftRightMost(Stack<TreeNode> store, TreeNode node) {
store.push(node);
node = node.left;
while (node != null) {
store.push(node);
while (node.left != null) {
store.push(node.left);
node = node.left;
}
node = node.right;
}
}