二叉树算法

3 阅读4分钟

以下是关于 二叉树算法 的详细整理,涵盖基础操作、遍历方法、常见问题及优化策略,附带代码示例(Python实现):


1. 二叉树基础

定义

  • 二叉树:每个节点最多有两个子节点(左子节点和右子节点)。

  • 常见类型

    • 二叉搜索树(BST):左子树所有节点值 ≤ 根节点值 ≤ 右子树所有节点值。

    • 平衡二叉树(如AVL、红黑树):通过旋转保持树高平衡,避免退化为链表。

    • 完全二叉树:除最后一层外,其他层节点全满,最后一层左对齐。


2. 基础算法与操作

(1) 遍历算法

遍历是二叉树算法的核心,分为 递归迭代 实现:

| 遍历方式 | 顺序 | 应用场景 |

|--------------|-----------------------|---------------------------|

| 前序遍历 | 根 → 左 → 右 | 复制树、表达式树求值 |

| 中序遍历 | 左 → 根 → 右 | 二叉搜索树获取有序序列 |

| 后序遍历 | 左 → 右 → 根 | 释放树内存、后缀表达式计算 |

| 层序遍历 | 按层从左到右访问节点 | 求树高、序列化树 |

代码示例


class TreeNode:

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

        self.val = val

        self.left = left

        self.right = right

# 递归前序遍历

def preorder(root):

    if not root:

        return []

    return [root.val] + preorder(root.left) + preorder(root.right)

# 迭代中序遍历(栈实现)

def inorder(root):

    stack, res = [], []

    while stack or root:

        while root:

            stack.append(root)

            root = root.left

        node = stack.pop()

        res.append(node.val)

        root = node.right

    return res

# 层序遍历(队列实现)

from collections import deque

def level_order(root):

    if not root:

        return []

    q = deque([root])

    res = []

    while q:

        level = []

        for _ in range(len(q)):

            node = q.popleft()

            level.append(node.val)

            if node.left:

                q.append(node.left)

            if node.right:

                q.append(node.right)

        res.append(level)

    return res

(2) 常见操作

  • 插入节点(BST):

    
    def insert(root, val):
    
        if not root:
    
            return TreeNode(val)
    
        if val < root.val:
    
            root.left = insert(root.left, val)
    
        else:
    
            root.right = insert(root.right, val)
    
        return root
    
    
  • 删除节点(BST):

    • 若节点无子节点:直接删除。

    • 若有一个子节点:用子节点替代。

    • 若有两个子节点:用右子树最小节点或左子树最大节点替代。

    
    def delete(root, val):
    
        if not root:
    
            return None
    
        if val < root.val:
    
            root.left = delete(root.left, val)
    
        elif val > root.val:
    
            root.right = delete(root.right, val)
    
        else:
    
            if not root.left:
    
                return root.right
    
            elif not root.right:
    
                return root.left
    
            # 找右子树的最小节点
    
            min_node = root.right
    
            while min_node.left:
    
                min_node = min_node.left
    
            root.val = min_node.val
    
            root.right = delete(root.right, min_node.val)
    
        return root
    
    
  • 查找节点(BST):

    
    def search(root, val):
    
        if not root:
    
            return False
    
        if root.val == val:
    
            return True
    
        elif val < root.val:
    
            return search(root.left, val)
    
        else:
    
            return search(root.right, val)
    
    

3. 高频算法问题

(1) 求二叉树的最大深度


def max_depth(root):

    if not root:

        return 0

    return 1 + max(max_depth(root.left), max_depth(root.right))

(2) 验证二叉搜索树(BST)


def is_valid_bst(root, min_val=float('-inf'), max_val=float('inf')):

    if not root:

        return True

    if root.val <= min_val or root.val >= max_val:

        return False

    return (is_valid_bst(root.left, min_val, root.val) and

            is_valid_bst(root.right, root.val, max_val))

(3) 对称二叉树判断


def is_symmetric(root):

    def check(left, right):

        if not left and not right:

            return True

        if not left or not right:

            return False

        return (left.val == right.val and

                check(left.left, right.right) and

                check(left.right, right.left))

    return check(root.left, root.right) if root else True

(4) 二叉树最近公共祖先(LCA)


def lowest_common_ancestor(root, p, q):

    if not root or root == p or root == q:

        return root

    left = lowest_common_ancestor(root.left, p, q)

    right = lowest_common_ancestor(root.right, p, q)

    if left and right:

        return root

    return left if left else right

(5) 路径总和问题


def has_path_sum(root, target):

    if not root:

        return False

    if not root.left and not root.right:

        return target == root.val

    return (has_path_sum(root.left, target - root.val) or

            has_path_sum(root.right, target - root.val))


4. 优化与进阶

(1) 平衡二叉树调整(AVL树)

  • 平衡因子:左右子树高度差不超过1。

  • 旋转操作

    • 左旋(LL):右子树过深时,提升右子节点为根。

    • 右旋(RR):左子树过深时,提升左子节点为根。

    • 左右旋(LR):先左旋再右旋。

    • 右左旋(RL):先右旋再左旋。

(2) 二叉树的序列化与反序列化


def serialize(root):

    if not root:

        return "None"

    return f"{root.val},{serialize(root.left)},{serialize(root.right)}"

def deserialize(data):

    nodes = data.split(',')

    def build():

        val = nodes.pop(0)

        if val == "None":

            return None

        node = TreeNode(int(val))

        node.left = build()

        node.right = build()

        return node

    return build()


5. 应用场景

  • 数据库索引:B树、B+树(基于平衡多路搜索树)。

  • 数据压缩:霍夫曼编码树(最小带权路径长度优先)。

  • 表达式解析:前/中/后缀表达式树。

  • 决策模型:决策树用于分类和回归。


学习建议

  1. 掌握递归思维:二叉树问题天然适合递归解决(如遍历、深度计算)。

  2. 画图辅助理解:手动模拟插入、删除、旋转等操作。

  3. 刷题巩固:LeetCode题库推荐题目:

  1. 进阶学习:红黑树、Treap、线段树等高级结构。

理解二叉树算法是掌握树形结构和复杂算法(如动态规划、图算法)的重要基础,建议通过实际编码和问题拆解加深理解!