定义

AVL 树是由 G. M. Adelson-Velsky 和 E. M. Landis 于 1962 年提出的自平衡二叉搜索树。1

其核心性质:对于任意节点,其左右子树的高度差(平衡因子)不超过 1

当插入或删除节点导致平衡性被破坏时,通过 旋转 操作在 时间内恢复平衡。


性质

性质说明
BST 性质左子树所有节点小于根,右子树所有节点大于根
平衡条件任意节点的平衡因子
高度,因此各操作时间为

平衡因子


旋转操作

当某个节点的平衡因子绝对值大于 1 时,需要通过旋转来恢复平衡。

单旋(两种情况)

左左情况(LL)

     z                      y
    / \                    / \
   y   T4      -->        x   z
  / \                      /  / \
 x   T3                   T1 T2  T3
/ \
T1 T2

右右情况(RR)

   z                      y
  / \                    / \
 T1  y       -->        z   x
    / \                / \  / \
   T2  x               T1 T2 T3 T4
      / \
     T3  T4

双旋(两种情况)

左右情况(LR)

   z                      z                      x
  / \                    / \                    / \
 y   T4      -->        x   T4      -->        y   z
/ \                      / \                  / \ / \
T1  x                    y  T3               T1 T2 T3 T4
   / \                  / \
  T2 T3                T1 T2

先对 做 RR 旋转,再对 做 LL 旋转。

右左情况(RL)

 z                       z                      x
/ \                     / \                    / \
T1  y       -->       T1  x        -->        z   y
   / \                    / \              / \ / \
  x  T4                   T2  y           T1 T2 T3 T4
  / \                        / \
 T2 T3                      T3 T4

先对 做 LL 旋转,再对 做 RR 旋转。


C++ 实现

#include <bits/stdc++.h>
using namespace std;
 
struct Node {
    int key;           // 键值
    int height;        // 节点高度
    Node *left;        // 左子节点
    Node *right;       // 右子节点
    Node(int k) : key(k), height(1), left(nullptr), right(nullptr) {}
};
 
class AVLTree {
private:
    Node* root;
 
    // 获取节点高度
    int height(Node* node) {
        return node ? node->height : 0;
    }
 
    // 获取平衡因子
    int balanceFactor(Node* node) {
        return node ? height(node->left) - height(node->right) : 0;
    }
 
    // 更新节点高度
    void updateHeight(Node* node) {
        if (node) {
            node->height = 1 + max(height(node->left), height(node->right));
        }
    }
 
    // 左左旋转(LL)
    Node* rotateLL(Node* z) {
        Node* y = z->left;
        z->left = y->right;
        y->right = z;
        updateHeight(z);
        updateHeight(y);
        return y;
    }
 
    // 右右旋转(RR)
    Node* rotateRR(Node* z) {
        Node* y = z->right;
        z->right = y->left;
        y->left = z;
        updateHeight(z);
        updateHeight(y);
        return y;
    }
 
    // 左右旋转(LR)
    Node* rotateLR(Node* z) {
        z->left = rotateRR(z->left);
        return rotateLL(z);
    }
 
    // 右左旋转(RL)
    Node* rotateRL(Node* z) {
        z->right = rotateLL(z->right);
        return rotateRR(z);
    }
 
    // 重新平衡
    Node* rebalance(Node* node) {
        updateHeight(node);
        int bf = balanceFactor(node);
 
        // 左子树更高
        if (bf > 1) {
            if (balanceFactor(node->left) >= 0) {
                // 左左情况
                return rotateLL(node);
            } else {
                // 左右情况
                return rotateLR(node);
            }
        }
        // 右子树更高
        if (bf < -1) {
            if (balanceFactor(node->right) <= 0) {
                // 右右情况
                return rotateRR(node);
            } else {
                // 右左情况
                return rotateRL(node);
            }
        }
        return node;
    }
 
    // 插入
    Node* insert(Node* node, int key) {
        if (!node) return new Node(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;
        }
 
        return rebalance(node);
    }
 
    // 查找最小节点
    Node* minNode(Node* node) {
        while (node->left) node = node->left;
        return node;
    }
 
    // 删除
    Node* erase(Node* node, int key) {
        if (!node) return nullptr;
 
        if (key < node->key) {
            node->left = erase(node->left, key);
        } else if (key > node->key) {
            node->right = erase(node->right, key);
        } else {
            // 找到要删除的节点
            if (!node->left || !node->right) {
                Node* temp = node->left ? node->left : node->right;
                delete node;
                return temp;
            } else {
                // 左右子树都存在,用后继替换
                Node* successor = minNode(node->right);
                node->key = successor->key;
                node->right = erase(node->right, successor->key);
            }
        }
 
        return rebalance(node);
    }
 
    // 中序遍历(用于调试)
    void inorder(Node* node) {
        if (!node) return;
        inorder(node->left);
        cout << node->key << " ";
        inorder(node->right);
    }
 
public:
    AVLTree() : root(nullptr) {}
 
    void insert(int key) {
        root = insert(root, key);
    }
 
    void erase(int key) {
        root = erase(root, key);
    }
 
    bool find(int key) {
        Node* cur = root;
        while (cur) {
            if (key < cur->key) cur = cur->left;
            else if (key > cur->key) cur = cur->right;
            else return true;
        }
        return false;
    }
 
    void inorder() {
        inorder(root);
        cout << endl;
    }
};

使用示例

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
 
    AVLTree avl;
    vector<int> keys = {10, 20, 30, 40, 50, 25};
 
    for (int key : keys) {
        avl.insert(key);
        cout << "插入 " << key << " 后的中序遍历: ";
        avl.inorder();
    }
 
    avl.erase(30);
    cout << "删除 30 后的中序遍历: ";
    avl.inorder();
 
    cout << "查找 25: " << (avl.find(25) ? "找到" : "未找到") << endl;
    cout << "查找 100: " << (avl.find(100) ? "找到" : "未找到") << endl;
 
    return 0;
}

时间复杂度

操作平均时间复杂度最坏时间复杂度
查找
插入
删除

与其他平衡树的比较

数据结构插入/删除查找实现难度备注
AVL 树中等高度平衡,查找性能好
红黑树中等高度大致平衡,插入删除开销小
Treap简单随机化,代码简洁
Splay 树(均摊)(均摊)简单访问局部性好

AVL 树比红黑树更严格,因此查找性能更好;但插入删除可能需要更多旋转。


参考资料

Footnotes

  1. Adelson-Velsky, G., & Landis, E. (1962). An algorithm for the organization of information. Soviet Mathematics Doklady, 3, 1259-1263.