C++ AVL树

一、AVL树的核心概念

1.1 为何需要AVL树?

普通二叉搜索树(BST)在理想情况下具有O(log n)的查询效率,但在极端情况下(如插入有序序列)会退化为链表,导致时间复杂度恶化为O(n)。这种现象被称为"单枝树"或"歪脖子树"。AVL树通过引入自平衡机制,确保任意节点的左右子树高度差绝对值不超过1,从而维持树的平衡性。

1.2 AVL树的数学特性

AVL树满足以下两个条件:

  • 左右子树均为AVL树
  • 任意节点的左右子树高度差 ∈ {-1, 0, 1}

这种严格的高度平衡特性使得AVL树的高度h与节点数n满足:

cpp 复制代码
h ≈ 1.44 log₂(n+2) - 0.328

相比BST的最坏情况,AVL树将查找、插入、删除的时间复杂度稳定在O(log n)级别。

二、AVL树的结构设计

2.1 节点定义

cpp 复制代码
template <class K, class V>
struct AVLTreeNode {
    pair<K, V> _kv;            // 键值对存储
    AVLTreeNode* _left;        // 左子节点
    AVLTreeNode* _right;       // 右子节点
    AVLTreeNode* _parent;      // 父节点(三叉链结构)
    int _bf;                   // 平衡因子(Balance Factor)

    AVLTreeNode(const pair<K, V>& kv)
        : _kv(kv), _left(nullptr), _right(nullptr), 
          _parent(nullptr), _bf(0) {}
};

关键设计点

  • 采用三叉链结构(包含parent指针)
  • 平衡因子_bf = 右子树高度 - 左子树高度
  • KV模型支持键值对存储

2.2 核心成员函数

cpp 复制代码
template <class K, class V>
class AVLTree {
public:
    bool Insert(const pair<K, V>& kv);  // 插入操作
    bool Remove(const K& key);          // 删除操作
    Node* Find(const K& key);           // 查找操作
private:
    Node* _root = nullptr;
    // 平衡维护相关辅助函数
    void RotateLeft(Node* parent);      // 左旋
    void RotateRight(Node* parent);     // 右旋
    void UpdateHeight(Node* node);      // 高度更新
};

三、旋转操作详解

3.1 基础旋转

3.1.1 左旋(Left Rotation)

条件:右子树高度 - 左子树高度 ≥ 2

cpp 复制代码
template <typename K, typename V>
void AVLTree<K,V>::RotateLeft(Node* parent) {
    Node* subR = parent->right;
    Node* subRL = subR->left;
    
    parent->right = subRL;
    if (subRL) subRL->parent = parent;

    Node* ppNode = parent->parent;
    subR->left = parent;
    parent->parent = subR;

    // 更新父指针关系
    if (ppNode == nullptr) {
        _root = subR;
        subR->parent = nullptr;
    } else {
        if (ppNode->left == parent) {
            ppNode->left = subR;
        } else {
            ppNode->right = subR;
        }
        subR->parent = ppNode;
    }

    // 更新平衡因子
    UpdateHeight(parent);
    UpdateHeight(subR);
}
3.1.2 右旋(Right Rotation)

触发条件 :左子树高度 - 右子树高度 ≥ 2
操作步骤与左旋对称。

3.2 复合旋转

3.2.1 左-右旋(Left-Right Rotation)

场景 :父节点左倾,左子节点右倾
处理步骤

  1. 对左子节点进行左旋
  2. 对父节点进行右旋
3.2.2 右-左旋(Right-Left Rotation)

场景 :父节点右倾,右子节点左倾
处理步骤

  1. 对右子节点进行右旋
  2. 对父节点进行左旋

四、插入操作实现

4.1 插入流程

cpp 复制代码
bool AVLTree<K,V>::Insert(const pair<K, V>& kv) {
    if (_root == nullptr) {
        _root = new Node(kv);
        return true;
    }

    Node* cur = _root;
    Node* parent = nullptr;
    while (cur) {
        if (cur->_kv.first < kv.first) {
            parent = cur;
            cur = cur->_right;
        } else if (cur->_kv.first > kv.first) {
            parent = cur;
            cur = cur->_left;
        } else {
            return false; // 重复键值
        }
    }

    cur = new Node(kv);
    if (parent->_kv.first < kv.first) {
        parent->_right = cur;
    } else {
        parent->_left = cur;
    }
    cur->_parent = parent;

    // 平衡因子更新与旋转
    while (parent) {
        // 更新平衡因子
        if (cur == parent->_left) {
            parent->_bf--;
        } else {
            parent->_bf++;
        }

        if (parent->_bf == 0) break; // 已平衡
        if (parent->_bf == 1 || parent->_bf == -1) {
            // 继续向上更新
            cur = parent;
            parent = parent->_parent;
        } else {
            // 需要旋转
            if (parent->_bf == 2) {
                if (parent->_right->_bf == 1) {
                    RotateLeft(parent);
                } else {
                    RotateRight(parent->_right);
                    RotateLeft(parent);
                }
            } else { // parent->_bf == -2
                if (parent->_left->_bf == -1) {
                    RotateRight(parent);
                } else {
                    RotateLeft(parent->_left);
                    RotateRight(parent);
                }
            }
            break; // 旋转后子树高度不变,无需继续更新
        }
    }
    return true;
}

AVL树通过平衡策略,在动态数据处理场景中展现出卓越的性能稳定性。尽管其旋转操作实现相对复杂,但其O(log n)的稳定时间复杂度使其成为许多高性能系统的首选数据结构。

相关推荐
西幻凌云1 小时前
认识STLstack容器
c++·stl·适配器·stack·序列式容器
繁华似锦respect1 小时前
C++ 设计模式之观察者模式详细介绍
linux·开发语言·c++·windows·观察者模式·设计模式·visual studio
威桑1 小时前
一个 CMake 项目是否只能有一个 install 目录?
linux·c++·cmake
爪哇部落算法小助手1 小时前
每日两题day61
数据结构·c++·算法
曼巴UE51 小时前
UE5 C++ 多播绑定执行演示
c++·ue5
裤裤兔1 小时前
利用matlab进行FDR校正的实现方式
数据结构·算法·matlab·多重比较矫正·校正·fdr
敲代码的嘎仔1 小时前
LeetCode面试HOT100—— 206. 反转链表
java·数据结构·学习·算法·leetcode·链表·面试
froginwe111 小时前
CSS Text(文本)详解
开发语言
自然语1 小时前
深度学习时代结束了,2025年开始只剩下轮廓
数据结构·人工智能·深度学习·学习·算法