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

二叉树高频考点:由后序+中序遍历推导前序与层序遍历(附完整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

核心口诀

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

相关推荐
旋生万物22 分钟前
电磁力 = 螺旋联络的 90° 旋转?麦克斯韦方程组的几何重构
人工智能·python·算法·机器学习·copilot·世界模型·物理ai
久久学姐44 分钟前
【AI问答】python引入其他模块的对象
python·绝对导入·相对导入·目录结构·模块导入
余俊晖1 小时前
多模态大模型细粒度视觉理解:Vision-OPD在线策略自蒸馏技术方案概述
人工智能·深度学习·算法·多模态·opd
脚踏实地皮皮晨1 小时前
003003001_Grid控件
开发语言·windows·算法·c#·visual studio
always_TT1 小时前
【Python requirements.txt 依赖管理】
开发语言·python
Hi李耶1 小时前
【LeetCode】6-Z字形变换
算法·leetcode·职场和发展
XiaoYu1__1 小时前
算法进阶·其一:用SCC、Tarjan算法与缩点思想解决有向图的连通关系及2-SAT问题的拓展
算法
小O的算法实验室1 小时前
AAAI-26,全局相关性学习:通过谱图神经网络增强进化算法
神经网络·学习·算法
段一凡-华北理工大学2 小时前
AI推动工业智能化转型~系列文章07:分类与诊断算法体系:故障识别的完整工具箱
数据库·人工智能·算法·机器学习·分类·数据挖掘·高炉炼铁智能化
简信CRM2 小时前
适合离散制造中小工厂 MES 系统推荐
算法·机器学习·制造