二叉树高频考点:后序+中序推导前序与层序遍历

二叉树高频考点:由后序+中序遍历推导前序与层序遍历(附完整Python代码)

> 摘要:二叉树遍历是算法面试的必考题型。本文从原理到代码,完整拆解"后序+中序→前序/层序"的推导过程,包含详细图解、可运行代码及4大避坑指南,建议收藏备用。


一、四种遍历方式速览

二叉树遍历的本质是根节点、左子树、右子树访问顺序的不同:

遍历方式 访问顺序 类型 作用
前序遍历 根 → 左 → 右 DFS 目标输出
中序遍历 左 → 根 → 右 DFS 🔑 分割左右子树
后序遍历 左 → 右 → 根 DFS 🔑 确定根节点
层序遍历 从上到下、从左到右 BFS 目标输出

> 核心结论 :只要知道后序 + 中序,就能唯一确定一棵二叉树,进而推导任意遍历结果。


二、重建二叉树的核心逻辑

2.1 算法步骤(三步走)

① 找根节点:后序遍历的最后一个元素 = 当前子树的根

② 分割子树:在中序遍历中找到根的位置,左侧=左子树,右侧=右子树

③ 递归重建:对左右子树重复步骤①②

2.2 关键细节:必须先右后左!

⚠️ 避坑重点 :递归重建时,必须先重建右子树,再重建左子树

原因 :我们使用 post.pop() 从后序数组末尾取元素,先取出的是右子树的根节点。若先建左子树,会导致节点匹配错误,重建失败。


三、完整Python实现

python 复制代码
from collections import deque

class TreeNode:
    """二叉树节点定义"""
    def __init__(self, val=0):
        self.val = val
        self.left = None
        self.right = None


def build_tree(inorder, postorder):
    """
    根据中序和后序遍历重建二叉树
    :param inorder: 中序遍历列表 [左→根→右]
    :param postorder: 后序遍历列表 [左→右→根]
    :return: 二叉树根节点
    """
    if not inorder:
        return None
    
    # 步骤1:后序末尾元素 = 当前根节点
    root_val = postorder.pop()
    root = TreeNode(root_val)
    
    # 步骤2:在中序中定位根节点,分割左右子树
    mid_idx = inorder.index(root_val)
    
    # 步骤3:⚠️ 必须先建右子树,再建左子树(适配pop()顺序)
    root.right = build_tree(inorder[mid_idx + 1:], postorder)
    root.left = build_tree(inorder[:mid_idx], postorder)
    
    return root


def preorder_traversal(root):
    """前序遍历:根 → 左 → 右(递归版)"""
    if not root:
        return []
    return [root.val] + preorder_traversal(root.left) + preorder_traversal(root.right)


def level_order_traversal(root):
    """层序遍历:BFS队列实现,按层分组返回"""
    if not root:
        return []
    
    q = deque([root])
    res = []
    
    while q:
        level_size = len(q)      # 🔑 记录当前层节点数
        current_level = []
        
        for _ in range(level_size):
            node = q.popleft()
            current_level.append(node.val)
            
            if node.left:
                q.append(node.left)
            if node.right:
                q.append(node.right)
        
        res.append(current_level)
    
    return res


# ==================== 测试用例 ====================
if __name__ == "__main__":
    inorder = [9, 3, 15, 20, 7]
    postorder = [9, 15, 7, 20, 3]
    
    # 1. 重建二叉树
    root = build_tree(inorder, postorder)
    
    # 2. 推导前序遍历
    preorder = preorder_traversal(root)
    
    # 3. 推导层序遍历(两种格式)
    level_order = level_order_traversal(root)
    level_flat = [val for level in level_order for val in level]
    
    print(f"中序遍历:{inorder}")
    print(f"后序遍历:{postorder}")
    print(f"前序遍历:{preorder}")
    print(f"层序遍历(按层):{level_order}")
    print(f"层序遍历(扁平):{level_flat}")

四、运行结果与图解

4.1 输出结果

中序遍历:9, 3, 15, 20, 7

后序遍历:9, 15, 7, 20, 3

前序遍历:3, 9, 20, 15, 7

层序遍历(按层):\[3, 9, 20, 15, 7]

层序遍历(扁平):3, 9, 20, 15, 7

4.2 重建过程图解

以测试用例为例,重建步骤如下:

后序:9, 15, 7, 20, 3 → 根=3

中序:9, 3, 15, 20, 7 → 左=9, 右=15,20,7

复制代码
    3
   / \
  9  [15,20,7]

后序弹出20 → 右子树根=20

中序15,20,7 → 左=15, 右=7

复制代码
    3
   / \
  9   20
     /  \
   15    7

4.3 遍历路径可视化

前序遍历路径(根→左→右):3 → 9 → 20 → 15 → 7

层序遍历路径(逐层访问):

第1层:3

第2层:9, 20

第3层:15, 7

五、四大避坑指南

坑点 错误做法 正确做法
1. 递归顺序 先左后右 ⚠️ 必须先右后左(适配pop())
2. 重复节点 直接用index() 用字典预存中序索引,避免值重复干扰
3. 层序层级混乱 不记录当前层节点数 level_size控制每层遍历次数
4. 空树边界 忘记处理空列表 入口处判断if not inorder: return None

核心口诀

后序找根,中序分边,先右后左,重建完成

相关推荐
兵慌码乱11 小时前
基于 MediaPipe 与 PySide2 的手势交互音乐控制系统实现:轻量化视觉交互全流程解析
python·opencv·计算机视觉·人机交互·手势识别·mediapipe·pyside2
luckdewei14 小时前
FastAPI 资产管理系统实战:复杂 ORM 关联、Alembic 迁移与 N+1 查询优化
python
aqi0020 小时前
15天学会AI应用开发(八)使用向量数据库实现RAG功能
人工智能·python·大模型·ai编程·ai应用
Csvn21 小时前
`functools.lru_cache` —— 一行代码搞定缓存加速
后端·python
JieE2121 天前
LeetCode 101. 对称二叉树|JS 递归 + 迭代双解法,彻底搞懂镜像判断
javascript·算法
金銀銅鐵2 天前
[Python] 从《千字文》中随机挑选汉字
后端·python
cup112 天前
[技术复盘] Windows Python 打包实战:Nuitka 环境踩坑总结与 CI 自动化构建全指南
python·ai·环境变量·ci·nuitka·skill
aqi002 天前
15天学会AI应用开发(七)有了大模型为什么还要引入RAG
人工智能·python·大模型·ai编程·ai应用