二叉树遍历终极指南:从入门到精通的前中后序+层序全解析

二叉树遍历终极指南:从入门到精通的前中后序+层序全解析

【免费下载链接】LeetCode-Book 《剑指 Offer》 Python, Java, C++ 解题代码,LeetBook《图解算法数据结构》配套代码仓 【免费下载链接】LeetCode-Book 项目地址: https://gitcode.com/GitHub_Trending/le/LeetCode-Book

二叉树遍历是算法面试中的高频考点,掌握不同遍历方式的实现原理和应用场景,能显著提升解题效率。本文将系统讲解前序、中序、后序三种深度优先遍历(DFS)和层序遍历(BFS)的实现方法,结合GitHub_Trending/le/LeetCode-Book中的经典例题,帮助读者快速掌握树结构的核心操作。

树遍历基础概念

二叉树(Binary Tree)是每个节点最多拥有两个子节点的树结构,遍历(Traversal)则是按某种规则访问树中所有节点的过程。根据访问顺序的不同,可分为深度优先和广度优先两大类:

  • 深度优先遍历(DFS):沿着树的深度优先访问节点,包括前序(根-左-右)、中序(左-根-右)、后序(左-右-根)三种方式
  • 广度优先遍历(BFS):按层次顺序访问节点,又称层次遍历

遍历顺序可视化

以下是三种DFS遍历顺序的示意图(以[剑指 Offer 32 - I. 从上到下打印二叉树](https://link.gitcode.com/i/37c06361df6c0b4488a3abf7fd1a085a/blob/c12faa39f70b5ddbcd2830db88ac74fea599442b/sword_for_offer/docs/剑指 Offer 32 - I. 从上到下打印二叉树.md?utm_source=gitcode_repo_files)中的示例树为例):

mermaid

  • 前序遍历:A → B → D → E → C → F → G
  • 中序遍历:D → B → E → A → F → C → G
  • 后序遍历:D → E → B → F → G → C → A
  • 层序遍历:A → B → C → D → E → F → G

深度优先遍历(DFS)实现

1. 前序遍历(Pre-order)

前序遍历的访问顺序为:根节点 → 左子树 → 右子树,是最直观的遍历方式。

递归实现

递归实现逻辑清晰,直接按照定义编写:

# [sword_for_offer/codes/python/sfo_27_mirror_of_a_binary_tree_s2.py]
def preorder_traversal(root):
    result = []
    def dfs(node):
        if not node:
            return
        result.append(node.val)  # 访问根节点
        dfs(node.left)           # 递归左子树
        dfs(node.right)          # 递归右子树
    dfs(root)
    return result
迭代实现

使用栈(Stack)模拟递归过程,需要注意右子节点先入栈:

def preorder_traversal(root):
    if not root:
        return []
    result = []
    stack = [root]
    while stack:
        node = stack.pop()
        result.append(node.val)  # 访问根节点
        if node.right:           # 右子节点先入栈
            stack.append(node.right)
        if node.left:            # 左子节点后入栈
            stack.append(node.left)
    return result

2. 中序遍历(In-order)

中序遍历的访问顺序为:左子树 → 根节点 → 右子树,对二叉搜索树(BST)进行中序遍历可得到有序序列。

递归实现
def inorder_traversal(root):
    result = []
    def dfs(node):
        if not node:
            return
        dfs(node.left)           # 递归左子树
        result.append(node.val)  # 访问根节点
        dfs(node.right)          # 递归右子树
    dfs(root)
    return result
迭代实现

中序遍历的迭代实现相对复杂,需要先遍历至最左节点:

def inorder_traversal(root):
    result = []
    stack = []
    current = root
    while current or stack:
        # 遍历至最左节点
        while current:
            stack.append(current)
            current = current.left
        # 访问节点
        current = stack.pop()
        result.append(current.val)
        # 转向右子树
        current = current.right
    return result

3. 后序遍历(Post-order)

后序遍历的访问顺序为:左子树 → 右子树 → 根节点,常用于计算子树大小、删除节点等场景。

递归实现
def postorder_traversal(root):
    result = []
    def dfs(node):
        if not node:
            return
        dfs(node.left)           # 递归左子树
        dfs(node.right)          # 递归右子树
        result.append(node.val)  # 访问根节点
    dfs(root)
    return result
迭代实现(双栈法)

使用两个栈实现后序遍历,第一个栈用于遍历节点,第二个栈用于存储结果:

def postorder_traversal(root):
    if not root:
        return []
    result = []
    stack1 = [root]
    stack2 = []
    while stack1:
        node = stack1.pop()
        stack2.append(node.val)
        if node.left:
            stack1.append(node.left)
        if node.right:
            stack1.append(node.right)
    # 反转结果得到后序遍历
    return stack2[::-1]

广度优先遍历(BFS)实现

层序遍历按层次顺序访问节点,实现方式通常为队列(Queue):

基础层序遍历

# [sword_for_offer/docs/剑指 Offer 32 - I. 从上到下打印二叉树.md]
def level_order(root):
    if not root:
        return []
    result = []
    queue = [root]
    while queue:
        node = queue.pop(0)
        result.append(node.val)
        if node.left:
            queue.append(node.left)
        if node.right:
            queue.append(node.right)
    return result

分层层序遍历

如需将每层节点分开存储,可记录每层节点数量:

# [sword_for_offer/docs/剑指 Offer 32 - II. 从上到下打印二叉树 II.md]
def level_order(root):
    if not root:
        return []
    result = []
    queue = [root]
    while queue:
        level_size = len(queue)
        current_level = []
        for _ in range(level_size):
            node = queue.pop(0)
            current_level.append(node.val)
            if node.left:
                queue.append(node.left)
            if node.right:
                queue.append(node.right)
        result.append(current_level)
    return result

之字形层序遍历

实现锯齿形层序遍历,需要根据层数决定节点添加方向:

# [sword_for_offer/docs/剑指 Offer 32 - III. 从上到下打印二叉树 III.md]
def level_order(root):
    if not root:
        return []
    result = []
    queue = [root]
    is_even_level = False
    while queue:
        level_size = len(queue)
        current_level = []
        for _ in range(level_size):
            node = queue.pop(0)
            current_level.append(node.val)
            if node.left:
                queue.append(node.left)
            if node.right:
                queue.append(node.right)
        # 偶数层反转
        if is_even_level:
            current_level = current_level[::-1]
        result.append(current_level)
        is_even_level = not is_even_level
    return result

遍历算法应用场景

不同遍历方式适用于不同场景,以下是常见应用:

前序遍历

  • 树的拷贝
  • 前缀表达式求值
  • [LCR 124. 推理二叉树](https://link.gitcode.com/i/37c06361df6c0b4488a3abf7fd1a085a/blob/c12faa39f70b5ddbcd2830db88ac74fea599442b/leetbook_ioa/docs/LCR 124. 推理二叉树.md?utm_source=gitcode_repo_files)(根据前序遍历重建二叉树)

中序遍历

  • 二叉搜索树排序
  • [剑指 Offer 54. 二叉搜索树的第 k 大节点](https://link.gitcode.com/i/37c06361df6c0b4488a3abf7fd1a085a/blob/c12faa39f70b5ddbcd2830db88ac74fea599442b/sword_for_offer/docs/剑指 Offer 54. 二叉搜索树的第 k 大节点.md?utm_source=gitcode_repo_files)
  • 验证二叉搜索树

后序遍历

  • 计算树的深度
  • 删除树节点
  • [剑指 Offer 55 - I. 二叉树的深度](https://link.gitcode.com/i/37c06361df6c0b4488a3abf7fd1a085a/blob/c12faa39f70b5ddbcd2830db88ac74fea599442b/sword_for_offer/docs/剑指 Offer 55 - I. 二叉树的深度.md?utm_source=gitcode_repo_files)

层序遍历

  • 计算树的宽度
  • 寻找二叉树最底层最左边的值
  • [剑指 Offer 32 - III. 从上到下打印二叉树 III](https://link.gitcode.com/i/37c06361df6c0b4488a3abf7fd1a085a/blob/c12faa39f70b5ddbcd2830db88ac74fea599442b/sword_for_offer/docs/剑指 Offer 32 - III. 从上到下打印二叉树 III.md?utm_source=gitcode_repo_files)

遍历算法复杂度分析

遍历方式时间复杂度空间复杂度实现方式
前序遍历O(N)O(N)递归/迭代
中序遍历O(N)O(N)递归/迭代
后序遍历O(N)O(N)递归/迭代
层序遍历O(N)O(N)队列

其中N为二叉树节点数量,空间复杂度主要取决于栈/队列的大小,最坏情况下(斜树)为O(N),平均情况下为O(logN)。

总结与进阶

掌握二叉树遍历是学习更复杂树结构(如红黑树、B+树)的基础,建议通过以下步骤巩固学习:

  1. 实现四种遍历的递归与迭代版本
  2. 完成剑指 Offer 32 系列层序遍历题目
  3. 尝试 Morris 遍历(常数空间复杂度遍历方法)
  4. 解决[selected_coding_interview/docs/102. 二叉树的层序遍历.md](https://link.gitcode.com/i/37c06361df6c0b4488a3abf7fd1a085a/blob/c12faa39f70b5ddbcd2830db88ac74fea599442b/selected_coding_interview/docs/102. 二叉树的层序遍历.md?utm_source=gitcode_repo_files)等进阶题目

更多二叉树相关题目和解题代码,请参考项目官方文档和[剑指 Offer 题目分类](https://link.gitcode.com/i/37c06361df6c0b4488a3abf7fd1a085a/blob/c12faa39f70b5ddbcd2830db88ac74fea599442b/sword_for_offer/剑指 Offer 题目分类.md?utm_source=gitcode_repo_files)。通过系统练习,相信你能在面试中轻松应对各类树遍历问题!

【免费下载链接】LeetCode-Book 《剑指 Offer》 Python, Java, C++ 解题代码,LeetBook《图解算法数据结构》配套代码仓 【免费下载链接】LeetCode-Book 项目地址: https://gitcode.com/GitHub_Trending/le/LeetCode-Book

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

抵扣说明:

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

余额充值