1. 理论
AVL 树是由 Adelson-Velsky 和 Landis 提出的自平衡二叉搜索树,核心特性是左右子树的高度差(平衡因子)绝对值不超过 1(平衡因子 = 左子树高度 - 右子树高度)。它继承了二叉搜索树'左子树节点值 < 根节点值 < 右子树节点值'的排序特性,同时通过旋转操作(LL、RR、LR、RL 四种类型)解决普通二叉搜索树可能退化为链表的问题,确保树的高度始终维持在 O(log n) 级别。因此,AVL 树的插入、删除、查找操作时间复杂度均为 O(log n),适用于需要高效动态维护有序数据的场景。
在 BST 树中如果按顺序插入元素,树可能会退化为链表,导致时间复杂度从 O(log n) 变为 O(n)。AVL 树为了维护节点平衡引入了四个节点的旋转操作。
1.1 左孩子左子树太高了(右旋 LL)
当某个节点的左孩子的左子树过高时,需要进行右旋。以失衡节点为轴旋转,将左孩子提升为新的根节点。
伪代码:
child = node->left;
node->left = child->right;
child->right = node;
同时需要更新 node 和 child 节点的高度值。
1.2 右孩子的右子树太高了(左旋 RR)
当某个节点的右孩子的右子树过高时,需要进行左旋。同理,将右孩子提升为新的根节点,原根节点变为左孩子。
伪代码:
child = node->right;
node->right = child->left;
child->left = node;
1.3 左孩子的右子树太高了(LR)
当左孩子的右子树过高时,无法通过一次旋转完成平衡。解决方案是先对左孩子进行一次左旋,将其转化为 LL 情况,然后再对当前节点进行一次右旋。
伪代码:
left_rotate(child);
right_rotate(node);
1.4 右孩子的左子树太高了(RL)
当右孩子的左子树过高时,先对右孩子进行一次右旋,转化为 RR 情况,然后再对当前节点进行一次左旋。
伪代码:
right_rotate(child);
left_rotate(node);
2. 代码实现
2.1 框架搭建
使用 C++ 模板类实现 AVL 树,包含节点定义、高度管理、旋转操作及插入删除逻辑。
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
template<typename T, typename Comp = less<T>>
class AvlTree {
private:
struct Node {
(T data) : (data), (), (), () {}
T value;
Node* left;
Node* right;
height;
};
Node* root;
Comp compare;
queue<Node*> q;
{
(node == ) ;
node->height;
}
{
node->height = ((node->left), (node->right)) + ;
}
{
Node* child = node->right;
node->right = child->left;
child->left = node;
(node);
(child);
child;
}
{
Node* child = node->left;
node->left = child->right;
child->right = node;
(node);
(child);
child;
}
{
node->left = (node->left);
(node);
}
{
node->right = (node->right);
(node);
}
{
(node == ) (val);
(val == node->value) node;
((node->value, val)) {
node->right = (node->right, val);
((node->right) - (node->left) > ) {
Node* child = node->right;
((child->left) > (child->right)) {
node = (node);
} {
node = (node);
}
}
} ((val, node->value)) {
node->left = (node->left, val);
((node->left) - (node->right) > ) {
Node* child = node->left;
((child->left) > (child->right)) {
node = (node);
} {
node = (node);
}
}
}
(node);
node;
}
{
(node == ) ;
(node->value == val) {
(node->right == && node->left == ) {
node;
;
} (node->left == && node->right != ) {
Node* child = node->right;
node;
child;
} (node->left != && node->right == ) {
Node* child = node->left;
node;
child;
} {
((node->left) >= (node->right)) {
Node* pre = node->left;
(pre->right != ) pre = pre->right;
T data = pre->value;
node->value = data;
node->left = (node->left, pre->value);
} {
Node* rear = node->right;
(rear->left != ) rear = rear->left;
node->value = rear->value;
node->right = (node->right, rear->value);
}
}
} ((node->value, val)) {
node->right = (node->right, val);
} ((val, node->value)) {
node->left = (node->left, val);
}
((node->left) - (node->right) > ) {
Node* child = node->left;
((child->left) > (child->right)) {
node = (node);
} {
node = (node);
}
} ((node->right) - (node->left) > ) {
Node* child = node->right;
((child->left) > (child->right)) {
node = (node);
} {
node = (node);
}
}
(node);
node;
}
{
(node == ) ;
cout << node->value << ;
(node->left);
(node->right);
}
:
() : () {}
{
root = (root, val);
}
{
root = (root, val);
}
{
(root);
cout << endl;
}
{
q.(root);
(!q.()) {
length = q.();
( i = ; i <= length; i++) {
Node* cur = q.();
q.();
cout << cur->value << ;
(cur->left != ) q.(cur->left);
(cur->right != ) q.(cur->right);
}
cout << endl;
}
cout << endl;
}
};
{
AvlTree<> p;
( i = ; i <= ; i++) {
p.(i);
}
p.();
cout << << ;
p.();
cout << << endl;
p.();
;
}

