平衡二叉树(AVL树):高效自平衡的奥秘

平衡二叉树(AVL树) 是一种自平衡的二叉搜索树(BST),由苏联数学家Adelson-Velsky和Landis于1962年发明(因此得名AVL)。其核心特性是:任意节点的左右子树高度差(平衡因子)绝对值不超过1。这种平衡特性确保了高效的查找、插入和删除操作,时间复杂度始终为 O(log n)


核心特性

  1. 平衡因子(Balance Factor)
    每个节点的平衡因子 = 左子树高度 - 右子树高度
    取值范围:{-1, 0, 1}
    示例:若节点左子树高度为3,右子树高度为2,则平衡因子=1(合法)

  2. 自平衡机制
    当插入或删除节点导致平衡因子超出±1范围时,树会自动通过旋转操作恢复平衡。


四种旋转操作(关键维护手段)

假设节点 A 失衡(|BF| > 1),根据失衡类型进行旋转:

  1. 左旋(LL型失衡)
          A            B
         /            / \
        B     ->     C   A
       /
      C 

场景:A的右子树过高(BF = -2)且右子节点B的BF ≤ 0

  1. 右旋(RR型失衡)
        A                B
         \              / \
          B     ->     A   C
           \
            C 

场景:A的左子树过高(BF = 2)且左子节点B的BF ≥ 0

  1. 左右旋(LR型失衡)
          A              A            C
         /              /            / \
        B      ->      C      ->    B   A
         \            / 
          C          B 

场景:A的左子树过高(BF=2),但左子节点B的BF = -1
步骤:

  • 先对B左旋→转换为RR型
  • 再对A右旋
  1. 右左旋(RL型失衡)
        A                  A                C
         \                /                / \
          B      ->      C        ->      A   B
         /                  \ 
        C                    B 

场景:A的右子树过高(BF=-2),但右子节点B的BF = 1
步骤:

  • 先对B右旋→转换为LL型
  • 再对A左旋

AVL树操作复杂度

操作时间复杂度说明
查找O(log n)与普通BST相同
插入O(log n)需回溯至根节点并可能旋转
删除O(log n)同上,最多旋转O(1)次
旋转O(1)仅调整局部指针

AVL树 vs 红黑树

特性AVL树红黑树
平衡严格性严格(高度差≤1)宽松(最长路径≤2倍最短)
查找效率更高(更严格的平衡)稍低
插入/删除更频繁的旋转(维护成本高)旋转次数较少
适用场景读密集型(如数据库索引)写密集型(如STL map)

Java实现示例(插入与旋转)

class AVLNode {
    int key, height;
    AVLNode left, right;

    AVLNode(int key) {
        this.key = key;
        this.height = 1; // 新节点高度为1
    }
}

public class AVLTree {
    private AVLNode root;

    // 计算节点高度
    private int height(AVLNode node) {
        return (node == null) ? 0 : node.height;
    }

    // 计算平衡因子
    private int balanceFactor(AVLNode node) {
        return (node == null) ? 0 : height(node.left) - height(node.right);
    }

    // 右旋(RR型失衡)
    private AVLNode rightRotate(AVLNode y) {
        AVLNode x = y.left;
        AVLNode T2 = x.right;

        x.right = y;
        y.left = T2;

        // 更新高度
        y.height = Math.max(height(y.left), height(y.right)) + 1;
        x.height = Math.max(height(x.left), height(x.right)) + 1;
        return x; // 返回新的根节点
    }

    // 左旋(LL型失衡)
    private AVLNode leftRotate(AVLNode x) {
        AVLNode y = x.right;
        AVLNode T2 = y.left;

        y.left = x;
        x.right = T2;

        x.height = Math.max(height(x.left), height(x.right)) + 1;
        y.height = Math.max(height(y.left), height(y.right)) + 1;
        return y;
    }

    // 插入节点(核心)
    public AVLNode insert(AVLNode node, int key) {
        // 1. 标准BST插入
        if (node == null) return new AVLNode(key);
        if (key < node.key) 
            node.left = insert(node.left, key);
        else if (key > node.key) 
            node.right = insert(node.right, key);
        else 
            return node; // 重复值不插入

        // 2. 更新高度
        node.height = 1 + Math.max(height(node.left), height(node.right));

        // 3. 检查平衡因子并旋转
        int balance = balanceFactor(node);
        
        // RR型(左子树过高且新节点在左子树的左侧)
        if (balance > 1 && key < node.left.key) 
            return rightRotate(node);
        
        // LL型(右子树过高且新节点在右子树的右侧)
        if (balance < -1 && key > node.right.key) 
            return leftRotate(node);
        
        // LR型(左子树过高但新节点在左子树的右侧)
        if (balance > 1 && key > node.left.key) {
            node.left = leftRotate(node.left);
            return rightRotate(node);
        }
        
        // RL型(右子树过高但新节点在右子树的左侧)
        if (balance < -1 && key < node.right.key) {
            node.right = rightRotate(node.right);
            return leftRotate(node);
        }
        return node;
    }
}

应用场景

  • 数据库索引:需快速查找(如B+树底层优化)
  • 内存受限系统:高效存储有序数据
  • 实时应用:保证最坏情况下的操作性能

关键总结:AVL树通过严格的平衡约束和旋转操作,在动态数据集中维持高效操作,是计算机科学中平衡树理论的基石之一。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

代码的余温

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

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

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

打赏作者

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

抵扣说明:

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

余额充值