当然,下面是对 AVL 树(平衡二叉搜索树) 的详细讲解,适合用作入门到进阶的数据结构学习内容。


🌲 数据结构【AVL树】——自平衡的二叉搜索树详解


📚 目录

  1. AVL 树简介
  2. 为什么需要 AVL 树?
  3. AVL 树的性质
  4. 旋转操作(LL、RR、LR、RL)详解
  5. AVL 插入操作过程
  6. AVL 删除操作简述
  7. Python 示例代码
  8. 应用场景
  9. 常见面试题与考点
  10. 延伸阅读

1️⃣ AVL 树简介

AVL 树是一种自平衡的二叉搜索树(BST)。它在每次插入或删除节点后,自动通过旋转保持平衡,从而确保查询操作的时间复杂度为 O(log n)


2️⃣ 为什么需要 AVL 树?

普通的二叉搜索树(BST)在最坏情况下可能退化为链表,导致搜索效率降为 O(n):

举例:

插入顺序:1 → 2 → 3 → 4 → 5
BST 结构:单边树
查询 5 需要 5 步,效率极低

❗ 解决办法:每次插入后检查树的平衡性,并进行必要的旋转维护平衡


3️⃣ AVL 树的性质

  • 每个节点记录一个“平衡因子(Balance Factor)”:
    bf = height(left subtree) - height(right subtree)
  • 对每个节点:bf ∈ {-1, 0, 1}
    超出范围则说明不平衡,需要旋转恢复。
  • AVL 树的高度 h ≈ 1.44 × log₂(n),保证 查询效率稳定在 O(log n)

4️⃣ 旋转操作详解

🔁 失衡类型与旋转方式

类型插入方向恢复操作
LL左子树的左子树右旋
RR右子树的右子树左旋
LR左子树的右子树左旋再右旋
RL右子树的左子树右旋再左旋

✅ 示例:右旋(LL)

     A                        B
    /                        / \
   B     ==> 右旋        C     A
  /                             
 C                                

✅ 示例:左旋(RR)

   A                            B
    \                          / \
     B     ==> 左旋         A     C
      \                            
       C                            

5️⃣ AVL 插入操作步骤

  1. 像普通 BST 一样插入
  2. 回溯路径上 更新每个节点的高度
  3. 判断是否失衡(平衡因子 ∉ {-1, 0, 1});
  4. 根据 LL/RR/LR/RL 类型进行旋转;
  5. 返回新的根节点;

6️⃣ AVL 删除操作简述

删除比插入更复杂:

  1. 正常 BST 删除;
  2. 回溯更新高度;
  3. 若某节点失衡,根据子树高度进行相应旋转;
  4. 注意多次旋转可能连续发生;

7️⃣ Python AVL 树插入实现(简化版)

class TreeNode:
    def __init__(self, key):
        self.key = key
        self.left = None
        self.right = None
        self.height = 1

class AVLTree:
    def get_height(self, root):
        return root.height if root else 0

    def get_balance(self, root):
        return self.get_height(root.left) - self.get_height(root.right) if root else 0

    def right_rotate(self, y):
        x = y.left
        T2 = x.right
        x.right = y
        y.left = T2
        y.height = max(self.get_height(y.left), self.get_height(y.right)) + 1
        x.height = max(self.get_height(x.left), self.get_height(x.right)) + 1
        return x

    def left_rotate(self, x):
        y = x.right
        T2 = y.left
        y.left = x
        x.right = T2
        x.height = max(self.get_height(x.left), self.get_height(x.right)) + 1
        y.height = max(self.get_height(y.left), self.get_height(y.right)) + 1
        return y

    def insert(self, root, key):
        if not root:
            return TreeNode(key)
        elif key < root.key:
            root.left = self.insert(root.left, key)
        else:
            root.right = self.insert(root.right, key)

        # 更新高度
        root.height = 1 + max(self.get_height(root.left), self.get_height(root.right))

        # 检查平衡因子
        balance = self.get_balance(root)

        # 四种失衡情况
        if balance > 1 and key < root.left.key:
            return self.right_rotate(root)      # LL
        if balance < -1 and key > root.right.key:
            return self.left_rotate(root)       # RR
        if balance > 1 and key > root.left.key:
            root.left = self.left_rotate(root.left)   # LR
            return self.right_rotate(root)
        if balance < -1 and key < root.right.key:
            root.right = self.right_rotate(root.right)  # RL
            return self.left_rotate(root)

        return root

8️⃣ AVL 树应用场景

应用场景原因
数据库索引(部分)查询频繁,需维持高度平衡
词典、字符串搜索系统保持搜索性能,支持频繁插入/删除
内存索引结构实时性强,使用 AVL 能保持响应稳定

9️⃣ 常见面试题与考点

  • 设计一个支持插入、删除、查找的平衡搜索结构(可用 AVL);
  • 手写 AVL 插入与旋转过程;
  • AVL 和 红黑树 的对比(AVL 查询快、红黑树插入删除快);
  • 如何在 AVL 中查找第 k 小的元素?

🔍 10. 延伸阅读