二叉树的前序、中序、后序遍历是三种经典的深度优先遍历(DFS)方式,它们的区别仅在于访问根节点的时机不同。下面用一张表+详细说明帮你彻底搞懂:
📊 一、核心定义对比
表格
| 遍历类型 | 访问顺序 | 口诀 | 根节点位置 |
|---|---|---|---|
| 前序遍历 | 根 → 左子树 → 右子树 | 根左右 | 最先 |
| 中序遍历 | 左子树 → 根 → 右子树 | 左根右 | 中间 |
| 后序遍历 | 左子树 → 右子树 → 根 | 左右根 | 最后 |
✅ 共同点:
- 都是递归结构(每个子树都按相同规则处理)
- 时间复杂度:O(n)(每个节点访问一次)
- 空间复杂度:O(h)(h = 树高,递归栈或显式栈的深度)
🌰 二、举例说明(同一棵树)
以这棵二叉树为例:
A / \ B C / \ \ D E F表格
| 遍历类型 | 遍历结果 | 过程简述 |
|---|---|---|
| 前序 | A → B → D → E → C → F | 先记根A,再钻左子树(B→D→E),最后右子树(C→F) |
| 中序 | D → B → E → A → C → F | 先钻到最左(D),回溯记B,再右(E),回溯记A,再处理右子树(C→F) |
| 后序 | D → E → B → F → C → A | 先处理完左右子树(D,E,B 和 F,C),最后记根A |
⚙️ 三、各自优点与典型应用场景
1.前序遍历(Pre-order)
- 优点:
- 先处理根节点,适合需要“自顶向下”操作的场景
- 结构清晰,易于序列化/反序列化
- 典型应用:
✅复制二叉树(先创建根,再递归复制左右子树)
✅树的序列化(如 LeetCode 的[1,2,3,null,null,4,5]格式)
✅表达式树 → 前缀表达式(如+ 1 * 2 3)
✅目录结构导出(先输出父文件夹,再子文件夹)
2.中序遍历(In-order)
- 优点:
- 对二叉搜索树(BST)天然有序!
- 能反映“左 < 根 < 右”的逻辑顺序
- 典型应用:
✅BST 升序输出(验证 BST、找第 K 小元素)
✅表达式树 → 中缀表达式(如(1 + (2 * 3)),需加括号)
✅数据库索引遍历(B+树的中序即有序数据)
✅DOM 树节点顺序访问(前端开发)
3.后序遍历(Post-order)
- 优点:
- 先处理子节点,再处理根节点,适合“自底向上”计算
- 安全释放资源(子节点先销毁)
- 典型应用:
✅删除二叉树(先删左右子树,再删根,避免悬空指针)
✅计算目录大小(先算子目录大小,再累加到父目录)
✅表达式树 → 后缀表达式(逆波兰)(如1 2 3 * +)
✅编译器语法分析(先处理子表达式,再处理运算符)
💡 四、如何选择?
| 需求场景 | 推荐遍历 |
|---|---|
| 需要先知道根节点信息 | 前序 |
| 处理 BST 或需要有序结果 | 中序 |
| 需要子节点结果才能处理根节点 | 后序 |
🛠 五、代码模板(Python 递归)
# 前序遍历 def preorder(root): if not root: return [] return [root.val] + preorder(root.left) + preorder(root.right) # 中序遍历 def inorder(root): if not root: return [] return inorder(root.left) + [root.val] + inorder(root.right) # 后序遍历 def postorder(root): if not root: return [] return postorder(root.left) + postorder(root.right) + [root.val]✅ 总结一句话:
- 前序:做事先定调(先处理根)→ 用于复制、序列化
- 中序:做事讲顺序(左根右)→ 用于排序、表达式
- 后序:做事收尾好(后处理根)→ 用于删除、计算
掌握这三种遍历的本质区别和应用场景,就掌握了二叉树操作的“任督二脉”! 🌟