后序遍历之非递归实现
后序遍历的非递归方式
经过的路径 左 - 根 - 右
后序遍历时 根节点不先从栈中弹出 要在右子树被遍历后 再弹出
如何判断右子树被遍历完成
通过记录上一次遍历的节点
如果上一次遍历的是当前节点的右子树 代表此根节点也可以被遍历出来
入栈顺序 1 2 4 8 9 5 3 6 7
出栈顺序 8 4 9 2 5 1 6 3 7
1 2 4 8
1 2 9
1 5
3 6
7
入栈顺序 1 2 4 8 9 5 3 6 7
出栈顺序 8 9 4 5 2 6 7 3 1
1 2 4 8
1 2 4
1 2 4 9
1 2 4
1 2
1 2 5
1 2
1 3 6
1 3 7
1 3
1
节点出栈的逻辑有两种情况:
1)当前节点是叶子节点
2)上一次出栈的节点是当前节点的右孩子
public static void postOrderByLoop(TreeNode node) {
Stack<TreeNode> stack = new Stack<>();
// 使用指针 记录遍历到哪个节点
TreeNode p = node;
// 记录上一次访问的节点
TreeNode prev = null;
while (p != null || !stack.isEmpty()) {
// 入栈 把当前能读到的所有左孩子 存入栈中
while (p != null) {
stack.push(p);
p = p.left;
}
// 出栈 弹出栈顶元素 并找到其右孩子
if (!stack.isEmpty()) {
// 节点出栈的逻辑有两种情况:
// 1)当前节点是叶子节点
// 2)上一次出栈的节点是当前节点的右孩子
p = stack.pop();
if (p.right == null || prev == p.right){
System.out.print(p.val + " ");
prev = p;
p = null;
}else {
// 不满足出栈条件 是因为节点有右孩子 且右孩子没有被访问到
stack.push(p);
p = p.right;
}
}
}
}