AVL平衡树

AVL树是一种自平衡二叉搜索树,通过旋转操作保持树的平衡,确保查找、插入和删除操作的时间复杂度为O(log n)。

AVL树的核心原理

AVL树的关键特性是每个节点的平衡因子(左子树高度 – 右子树高度)绝对值不超过1。当插入或删除节点导致平衡因子绝对值超过1时,需要通过四种旋转操作来恢复平衡:

  1. 左旋(RR旋转):处理右子树比左子树高2且右子树的右子树更高的情况
  2. 右旋(LL旋转):处理左子树比右子树高2且左子树的左子树更高的情况
  3. 左右双旋(LR旋转):先对左子节点左旋,再对当前节点右旋
  4. 右左双旋(RL旋转):先对右子节点右旋,再对当前节点左旋

C++实现代码

#include <iostream>
#include <algorithm>

// AVL树节点结构
struct AVLNode {
    int key;
    AVLNode* left;
    AVLNode* right;
    int height;

    AVLNode(int k) : key(k), left(nullptr), right(nullptr), height(1) {}
};

class AVLTree {
private:
    AVLNode* root;

    // 获取节点高度
    int height(AVLNode* node) {
        return node ? node->height : 0;
    }

    // 计算平衡因子
    int getBalance(AVLNode* node) {
        return node ? height(node->left) - height(node->right) : 0;
    }

    // 右旋操作
    AVLNode* rightRotate(AVLNode* y) {
        AVLNode* x = y->left;
        AVLNode* T2 = x->right;

        // 执行旋转
        x->right = y;
        y->left = T2;

        // 更新高度
        y->height = std::max(height(y->left), height(y->right)) + 1;
        x->height = std::max(height(x->left), height(x->right)) + 1;

        return x;
    }

    // 左旋操作
    AVLNode* leftRotate(AVLNode* x) {
        AVLNode* y = x->right;
        AVLNode* T2 = y->left;

        // 执行旋转
        y->left = x;
        x->right = T2;

        // 更新高度
        x->height = std::max(height(x->left), height(x->right)) + 1;
        y->height = std::max(height(y->left), height(y->right)) + 1;

        return y;
    }

    // 插入节点辅助函数
    AVLNode* insert(AVLNode* node, int key) {
        // 1. 执行标准BST插入
        if (!node) 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 + std::max(height(node->left), height(node->right));

        // 3. 获取平衡因子检查是否平衡
        int balance = getBalance(node);

        // 如果不平衡,有4种情况

        // 左左情况
        if (balance > 1 && key < node->left->key)
            return rightRotate(node);

        // 右右情况
        if (balance < -1 && key > node->right->key)
            return leftRotate(node);

        // 左右情况
        if (balance > 1 && key > node->left->key) {
            node->left = leftRotate(node->left);
            return rightRotate(node);
        }

        // 右左情况
        if (balance < -1 && key < node->right->key) {
            node->right = rightRotate(node->right);
            return leftRotate(node);
        }

        return node;
    }

    // 查找最小节点
    AVLNode* minValueNode(AVLNode* node) {
        AVLNode* current = node;
        while (current->left)
            current = current->left;
        return current;
    }

    // 删除节点辅助函数
    AVLNode* deleteNode(AVLNode* root, int key) {
        // 1. 执行标准BST删除
        if (!root) return root;

        if (key < root->key)
            root->left = deleteNode(root->left, key);
        else if (key > root->key)
            root->right = deleteNode(root->right, key);
        else {
            // 节点有一个或没有子节点
            if (!root->left || !root->right) {
                AVLNode* temp = root->left ? root->left : root->right;

                // 没有子节点的情况
                if (!temp) {
                    temp = root;
                    root = nullptr;
                } else // 一个子节点的情况
                    *root = *temp; // 复制非空子节点内容

                delete temp;
            } else {
                // 节点有两个子节点:获取中序后继(右子树的最小值)
                AVLNode* temp = minValueNode(root->right);

                // 复制中序后继的数据到当前节点
                root->key = temp->key;

                // 删除中序后继
                root->right = deleteNode(root->right, temp->key);
            }
        }

        // 如果树只有一个节点则返回
        if (!root) return root;

        // 2. 更新当前节点的高度
        root->height = 1 + std::max(height(root->left), height(root->right));

        // 3. 获取平衡因子检查是否平衡
        int balance = getBalance(root);

        // 如果不平衡,有4种情况

        // 左左情况
        if (balance > 1 && getBalance(root->left) >= 0)
            return rightRotate(root);

        // 左右情况
        if (balance > 1 && getBalance(root->left) < 0) {
            root->left = leftRotate(root->left);
            return rightRotate(root);
        }

        // 右右情况
        if (balance < -1 && getBalance(root->right) <= 0)
            return leftRotate(root);

        // 右左情况
        if (balance < -1 && getBalance(root->right) > 0) {
            root->right = rightRotate(root->right);
            return leftRotate(root);
        }

        return root;
    }

    // 中序遍历辅助函数
    void inorder(AVLNode* node) {
        if (node) {
            inorder(node->left);
            std::cout << node->key << " ";
            inorder(node->right);
        }
    }

    // 前序遍历辅助函数
    void preorder(AVLNode* node) {
        if (node) {
            std::cout << node->key << " ";
            preorder(node->left);
            preorder(node->right);
        }
    }

public:
    AVLTree() : root(nullptr) {}

    // 插入节点
    void insert(int key) {
        root = insert(root, key);
    }

    // 删除节点
    void deleteKey(int key) {
        root = deleteNode(root, key);
    }

    // 中序遍历
    void inorder() {
        inorder(root);
        std::cout << std::endl;
    }

    // 前序遍历
    void preorder() {
        preorder(root);
        std::cout << std::endl;
    }

    // 查找节点
    AVLNode* search(int key) {
        AVLNode* current = root;
        while (current) {
            if (key < current->key)
                current = current->left;
            else if (key > current->key)
                current = current->right;
            else
                return current;
        }
        return nullptr;
    }
};

// 测试代码
int main() {
    AVLTree tree;

    // 测试插入
    tree.insert(10);
    tree.insert(20);
    tree.insert(30);
    tree.insert(40);
    tree.insert(50);
    tree.insert(25);

    std::cout << "前序遍历: ";
    tree.preorder(); // 应显示平衡后的树结构

    std::cout << "中序遍历: ";
    tree.inorder(); // 应显示有序序列

    // 测试删除
    tree.deleteKey(20);
    std::cout << "删除20后的中序遍历: ";
    tree.inorder();

    // 测试查找
    AVLNode* found = tree.search(30);
    if (found)
        std::cout << "找到节点30\n";
    else
        std::cout << "未找到节点30\n";

    return 0;
}

代码解析

  1. 节点结构AVLNode包含键值、左右子节点指针和高度信息。
  2. 旋转操作
    rightRotate处理LL不平衡情况
    leftRotate处理RR不平衡情况
    • 组合使用处理LR和RL不平衡情况
  3. 插入操作
    • 执行标准BST插入
    • 更新节点高度
    • 检查平衡因子并进行必要的旋转
  4. 删除操作
    • 执行标准BST删除
    • 更新节点高度
    • 检查平衡因子并进行必要的旋转
  5. 遍历操作:提供中序和前序遍历方法
  6. 查找操作:标准BST查找实现
滚动至顶部