1. 二叉树的前中后序遍历中递归与迭代(显式栈)实现,以及 Morris 遍历的 O(1) 空间原理?
二叉树的前中后序遍历,说明递归与迭代(显式栈)实现,以及 Morris 遍历的 O(1) 空间原理?
- 递归三序遍历
- 迭代显式栈实现
- Morris 遍历 O(1) 空间原理
递归:前序(根左右)、中序(左根右)、后序(左右根),代码简洁。迭代:前序用栈(根入栈,出栈访问,右左入栈);中序用栈(沿左链入栈,出栈访问后转向右子树);后序较复杂(用"prev 记录上次访问"或双栈/入栈标记)。Morris 遍历:O(1) 空间、O(n) 时间,利用"中序前驱节点"的右孩子原为 null 的特性做线索化——找当前节点的中序前驱(左子树最右),若其右孩子为 null 则设为当前节点(建立线索),访问后恢复;若右孩子已指向当前节点则说明左子树已遍历完,恢复右孩子为 null 并转向右子树。Morris 通过临时改建树(线索)避免栈,遍历完恢复原结构,故 O(1) 空间。
递归最直观,迭代用显式栈模拟递归,Morris 用"线索"实现 O(1) 空间。Morris 的核心是"利用空右指针记录回溯路径",访问后恢复。这是"空间最优遍历"的经典技巧,理解其线索化与恢复是关键。
// Morris 中序遍历
List<Integer> morrisInorder(TreeNode root) {
List<Integer> res = new ArrayList<>();
TreeNode cur = root, pre = null;
while (cur != null) {
if (cur.left == null) { res.add(cur.val); cur = cur.right; }
else {
pre = cur.left;
while (pre.right != null && pre.right != cur) pre = pre.right; // 找前驱
if (pre.right == null) { pre.right = cur; cur = cur.left; } // 建线索
else { pre.right = null; res.add(cur.val); cur = cur.right; } // 恢复
}
}
return res;
}