彻底搞懂二叉树的前序、中序、后序遍历

在学习和使用数据结构时,二叉树是最基础、也最容易考察的结构之一。而遍历方式,则是二叉树应用的入口。所谓「遍历」,是指按照某种规则,依次访问树中的每一个节点。而在众多遍历方式中,前序、中序、后序遍历是最经典、最基础、也最常用的三种。

本文将围绕这三种遍历方式,讲清楚如下几个问题:

  • 它们各自的定义和特点是什么?

  • 如何用递归与非递归两种方式实现?

  • 它们分别在工程中能干什么?

  • 实战题型:如何识别遍历顺序?如何用遍历序列还原树结构?

目录

二叉树的结构回顾

三种遍历的定义

递归实现:最简单但最易混淆的方法

非递归实现:堆栈模拟调用过程

工程应用场景与典型题型

前序遍历的常用场景

中序遍历的常用场景

后序遍历的常用场景

还原树结构

常见问题


二叉树的结构回顾

一个二叉树(Binary Tree)的每个节点至多有两个子节点,分别称为左子树和右子树。用代码表示通常是这样的结构:

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

我们将从根节点出发,按照不同顺序访问子节点,就得到了不同的遍历方式。


三种遍历的定义

  • 前序遍历(Pre-order):根节点 → 左子树 → 右子树

  • 中序遍历(In-order):左子树 → 根节点 → 右子树

  • 后序遍历(Post-order):左子树 → 右子树 → 根节点

以图中二叉树为例:遍历结果如下:

  • 前序遍历:A B D E C F

  • 中序遍历:D B E A C F

  • 后序遍历:D E B F C A

递归实现:最简单但最易混淆的方法

递归是实现树遍历最直接的方式,因为树结构天然是递归结构。

def preorder(root):
    if root:
        print(root.val)
        preorder(root.left)
        preorder(root.right)

def inorder(root):
    if root:
        inorder(root.left)
        print(root.val)
        inorder(root.right)

def postorder(root):
    if root:
        postorder(root.left)
        postorder(root.right)
        print(root.val)

非递归实现:堆栈模拟调用过程

前序遍历(非递归)

def preorder_iterative(root):
    if not root:
        return
    stack = [root]
    while stack:
        node = stack.pop()
        print(node.val)
        if node.right:
            stack.append(node.right)
        if node.left:
            stack.append(node.left)

中序遍历(非递归)

def inorder_iterative(root):
    stack = []
    node = root
    while stack or node:
        while node:
            stack.append(node)
            node = node.left
        node = stack.pop()
        print(node.val)
        node = node.right

后序遍历(非递归)这是最难的一个,我们可以借助两个栈,或者使用标记法:

def postorder_iterative(root):
    if not root:
        return
    stack = [root]
    out = []
    while stack:
        node = stack.pop()
        out.append(node.val)
        if node.left:
            stack.append(node.left)
        if node.right:
            stack.append(node.right)
    for val in reversed(out):
        print(val)

工程应用场景与典型题型

前序遍历的常用场景

  • 导出目录结构(根节点先输出)

  • 树结构序列化:先根,再子树,可以方便记录结构

中序遍历的常用场景

  • 二叉搜索树(BST)中序遍历即为升序排列

  • 应用于平衡检查、区间查找等功能

后序遍历的常用场景

  • 节点释放、后序处理(如计算子树大小)

  • 编译器抽象语法树(先处理子表达式)

还原树结构

给定中序遍历 + 前序/后序,可以唯一确定一棵二叉树

例如 前序 + 中序重建二叉树:

def buildTree(preorder, inorder):
    if not preorder:
        return None
    root = TreeNode(preorder[0])
    idx = inorder.index(root.val)
    root.left = buildTree(preorder[1:idx+1], inorder[:idx])
    root.right = buildTree(preorder[idx+1:], inorder[idx+1:])
    return root

常见问题

常见问题原因解决方式
遍历顺序写错递归调用顺序不对手写遍历过程画图推导
非递归实现死循环栈控制不当使用断点调试打印 stack 变化
子树为空时出错没有判断 None所有递归边界加 if not root: 检查
多个节点值相同使用 index() 找不到正确位置改为使用值 → 下标的字典
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

昊昊该干饭了

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值