一、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)
场景 :父节点左倾,左子节点右倾
处理步骤:
- 对左子节点进行左旋
- 对父节点进行右旋
3.2.2 右-左旋(Right-Left Rotation)
场景 :父节点右倾,右子节点左倾
处理步骤:
- 对右子节点进行右旋
- 对父节点进行左旋
四、插入操作实现
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)的稳定时间复杂度使其成为许多高性能系统的首选数据结构。