mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4mobile wallpaper 5mobile wallpaper 6
560 字
3 分钟
【算法笔记】(十一)二叉树遍历的非递归实现
2026-03-16
统计加载中...

先序遍历#

  1. 根节点先入栈
  2. 每次弹出一个节点就立即访问
  3. 为了保证左子树先处理,必须先压右,再压左
// 先序打印所有节点,非递归版
public static void preOrder(TreeNode head) {
if (head != null) {
Stack<TreeNode> stack = new Stack<>();
stack.push(head);
while (!stack.isEmpty()) {
head = stack.pop();
System.out.print(head.val + " ");
if (head.right != null) {
stack.push(head.right);
}
if (head.left != null) {
stack.push(head.left);
}
}
System.out.println();
}
}

中序遍历#

  1. 一路向左走,经过的节点全部压栈
  2. 走到最左边后,再开始弹栈访问
  3. 弹出某个节点之后,再去处理它的右子树
// 中序打印所有节点,非递归版
public static void inOrder(TreeNode head) {
if (head != null) {
Stack<TreeNode> stack = new Stack<>();
while (!stack.isEmpty() || head != null) {
if (head != null) {
stack.push(head);
head = head.left;
} else {
head = stack.pop();
System.out.print(head.val + " ");
head = head.right;
}
}
System.out.println();
}
}

后序遍历#

对于任意一个节点,只有当它的左右子树都处理完了,自己才能出栈被访问,因此核心问题是:怎么判断当前的栈顶节点的左右子树是否已经处理过?使用一个变量 h 来解决这个问题。

// 后序打印所有节点,非递归版
public static void posOrderOneStack(TreeNode h) {
if (h != null) {
Stack<TreeNode> stack = new Stack<>();
stack.push(h);
// 如果始终没有打印过节点,h就一直是头节点
// 一旦打印过节点,h就变成打印节点
// 之后h的含义:上一次打印的节点
while (!stack.isEmpty()) {
TreeNode cur = stack.peek();
if (cur.left != null && h != cur.left && h != cur.right) {
// 当前节点有左子树
// 并且最近处理过的节点不是它的左孩子,也不是它的右孩子
// 说明左右子树都还没处理到,那么先去处理左子树
stack.push(cur.left);
} else if (cur.right != null && h != cur.right) {
// 左子树已经处理过了,或者根本没有左子树
// 当前有右子树且右子树没有被处理,那么处理右子树
stack.push(cur.right);
} else {
// 左树、右树 没有 或者 都处理过了,那么当前节点就可以访问
// 访问之后把它记录到h里,表示这是最近一次处理完成的节点
System.out.print(cur.val + " ");
h = stack.pop();
}
}
System.out.println();
}
}
【算法笔记】(十一)二叉树遍历的非递归实现
http://hgqwd.icu/posts/suanfa11/
作者
天线宝宝死于谋杀
发布于
2026-03-16
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

封面
Sample Song
Sample Artist
封面
Sample Song
Sample Artist
0:00 / 0:00