一、AVL 树基础概念
1. 什么是 AVL 树?
AVL 树是自平衡二叉搜索树,由 Adelson-Velsky 和 Landis 提出。
核心规则:
-
满足二叉搜索树性质(左 < 根 < 右)
-
每个节点的左右子树高度差的绝对值 ≤ 1
-
每个节点维护一个平衡因子(Balance Factor, BF)
-
BF = 右子树高度 - 左子树高度 -
合法值:
-1、0、1 -
出现
2 / -2说明失衡,需要旋转调整
-
2. 平衡因子(BF)规则
-
插入左子树 → BF -1
-
插入右子树 → BF +1
-
BF = 0 → 高度不变,停止更新
-
BF = ±1 → 高度变化,继续向上更新
-
BF = ±2 → 失衡,必须旋转调整
二、AVL 树节点结构定义
#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
template<class K, class V>
struct AVLTreeNode
{
// 存储键值对
pair<K, V> _kv;
// 三叉链:左孩子、右孩子、父节点
AVLTreeNode<K, V>* _left;
AVLTreeNode<K, V>* _right;
AVLTreeNode<K, V>* _parent;
int _bf; // 平衡因子 balance factor
// 构造函数
AVLTreeNode(const pair<K, V>& kv)
:_kv(kv)
,_left(nullptr)
,_right(nullptr)
,_parent(nullptr)
,_bf(0)
{}
};
节点核心成员:
-
pair<K, V>:存储 key-value 数据 -
_left/_right/_parent:三叉链结构,方便旋转回溯 -
_bf:平衡因子,控制平衡
三、AVLTree 类整体结构
template<class K,class V>
class AVLTree
{
typedef AVLTreeNode<K, V> Node;
public:
// 插入接口
bool Insert(const pair<K, V>& kv);
// 左旋
void RotateL(Node* parent);
// 右旋
void RotateR(Node* parent);
// 右左旋
void RotateRL(Node* parent);
// 左右旋
void RotateLR(Node* parent);
// 求树高度
int Height();
int Height(Node* root);
// 判断是否平衡
bool IsBalance();
bool IsBalance(Node* root);
private:
Node* _root = nullptr; // 根节点
public:
int _rotateCount = 0; // 旋转次数统计
};
四、插入(Insert)核心逻辑
插入分为 3 步:
-
按照二叉搜索树规则插入节点
-
更新平衡因子 BF
-
如果失衡 → 旋转调整
1. BST 插入部分
// 1. 空树直接插入
if (_root == nullptr)
{
_root = new Node(kv);
return true;
}
// 2. 找插入位置
Node* parent = nullptr;
Node* cur = _root;
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 // key 重复,不插入
return false;
}
// 3. 链接新节点
cur = new Node(kv);
if (parent->_kv.first < cur->_kv.first)
parent->_right = cur;
else
parent->_left = cur;
cur->_parent = parent;
2. 平衡因子更新 + 旋转判断
// 回溯更新平衡因子
while (parent)
{
// 左孩子插入 → BF -1
if (cur == parent->_left)
parent->_bf--;
// 右孩子插入 → BF +1
else
parent->_bf++;
// ====================== 情况1 ======================
// BF = 0:高度没变,停止更新
if (parent->_bf == 0)
{
break;
}
// ====================== 情况2 ======================
// BF = ±1:高度变了,继续向上更新
else if (parent->_bf == 1 || parent->_bf == -1)
{
cur = parent;
parent = parent->_parent;
}
// ====================== 情况3 ======================
// BF = ±2:失衡 → 旋转
else if (parent->_bf == 2 || parent->_bf == -2)
{
// 旋转调整
if (parent->_bf == 2 && cur->_bf == 1)
{
RotateL(parent); // 左单旋
}
else if (parent->_bf == -2 && cur->_bf == -1)
{
RotateR(parent); // 右单旋
}
else if (parent->_bf == -2 && cur->_bf == 1)
{
RotateLR(parent); // 左右旋
}
else if (parent->_bf == 2 && cur->_bf == -1)
{
RotateRL(parent); // 右左旋
}
break;
}
else
assert(false); // 非法 BF
}
3. 四种旋转判断总结
| 失衡类型 | 条件 | 旋转方式 |
|---|---|---|
| 左左 | parent.*bf = -2,cur.*bf = -1 | 右旋 |
| 右右 | parent.*bf = 2,cur.*bf = 1 | 左旋 |
| 左右 | parent.*bf = -2,cur.*bf = 1 | 先左旋后右旋 |
| 右左 | parent.*bf = 2,cur.*bf = -1 | 先右旋后左旋 |
五、旋转实现(核心)
1. 左旋(RotateL)
适用场景:右右失衡
void RotateL(Node* parent)
{
++_rotateCount;
Node* cur = parent->_right;
Node* curleft = cur->_left;
// 1. cur 左孩子 给 parent 右孩子
parent->_right = curleft;
if (curleft)
curleft->_parent = parent;
// 2. parent 做 cur 的左孩子
cur->_left = parent;
// 3. 处理祖父节点
Node* ppnode = parent->_parent;
parent->_parent = cur;
if (parent == _root)
{
_root = cur;
cur->_parent = nullptr;
}
else
{
if (ppnode->_left == parent)
ppnode->_left = cur;
else
ppnode->_right = cur;
cur->_parent = ppnode;
}
// 旋转后平衡因子重置为 0
parent->_bf = cur->_bf = 0;
}
2. 右旋(RotateR)
适用场景:左左失衡
void RotateR(Node* parent)
{
++_rotateCount;
Node* cur = parent->_left;
Node* curright = cur->_right;
// 1. cur 右孩子 给 parent 左孩子
parent->_left = curright;
if (curright)
curright->_parent = parent;
// 2. parent 做 cur 的右孩子
cur->_right = parent;
parent->_parent = cur;
// 3. 处理祖父节点
Node* ppnode = parent->_parent;
if (ppnode == nullptr)
{
_root = cur;
cur->_parent = nullptr;
}
else
{
if (ppnode->_left == parent)
ppnode->_left = cur;
else
ppnode->_right = cur;
cur->_parent = ppnode;
}
parent->_bf = cur->_bf = 0;
}
3. 右左旋(RL)
适用场景:右左失衡
void RotateRL(Node* parent)
{
Node* cur = parent->_right;
Node* curleft = cur->_left;
int bf = curleft->_bf;
RotateR(parent->_right);
RotateL(parent);
// 精细调整平衡因子
if (bf == 0)
cur->_bf = curleft->_bf = parent->_bf = 0;
else if (bf == 1)
{
cur->_bf = 0;
curleft->_bf = 0;
parent->_bf = -1;
}
else if (bf == -1)
{
cur->_bf = 1;
curleft->_bf = 0;
parent->_bf = 0;
}
else
assert(false);
}
4. 左右旋(LR)
适用场景:左右失衡
void RotateLR(Node* parent)
{
Node* cur = parent->_left;
Node* curright = cur->_right;
int bf = curright->_bf;
RotateL(parent->_left);
RotateR(parent);
if (bf == 0)
parent->_bf = cur->_bf = curright->_bf = 0;
else if (bf == -1)
{
parent->_bf = 1;
cur->_bf = 0;
curright->_bf = 0;
}
else if (bf == 1)
{
parent->_bf = 0;
cur->_bf = -1;
curright->_bf = 0;
}
}
六、验证 AVL 树正确性
1. 求树高度
int Height()
{
return Height(_root);
}
int Height(Node* root)
{
if (root == nullptr)
return 0;
int leftHeight = Height(root->_left);
int rightHeight = Height(root->_right);
return max(leftHeight, rightHeight) + 1;
}
2. 判断是否为合法 AVL 树
检查两点:
-
每个节点左右高度差 ≤ 1
-
平衡因子
BF计算正确
bool IsBalance()
{
return IsBalance(_root);
}
bool IsBalance(Node* root)
{
if (root == nullptr)
return true;
int leftHight = Height(root->_left);
int rightHight = Height(root->_right);
// 检查平衡因子是否正确
if (rightHight - leftHight != root->_bf)
{
cout << "平衡因子异常:" << root->_kv.first << "->" << root->_bf << endl;
return false;
}
// 检查高度差
return abs(rightHight - leftHight) < 2
&& IsBalance(root->_left)
&& IsBalance(root->_right);
}
七、完整测试代码
void TestAVLTree()
{
AVLTree<int, int> t;
int a[] = { 4, 2, 6, 1, 3, 5, 7 };
for (auto e : a)
{
t.Insert(make_pair(e, e));
}
cout << "IsBalance: " << t.IsBalance() << endl;
cout << "Height: " << t.Height() << endl;
cout << "RotateCount: " << t._rotateCount << endl;
}
int main()
{
TestAVLTree();
return 0;
}
八、AVL 树知识点总结
1. 核心流程
插入 → 更新 BF → 判断失衡 → 旋转调整 → 验证平衡
2. 四种旋转
-
左左 → 右旋
-
右右 → 左旋
-
左右 → 左右旋
-
右左 → 右左旋
3. 平衡因子规则
-
BF = 右高 - 左高 -
合法:
-1/0/1 -
失衡:
±2
4. 性能
-
查找/插入/删除:O(logN)
-
效率高于普通 BST,不会退化成链表
九、代码完整可运行版
#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
template<class K, class V>
struct AVLTreeNode
{
pair<K, V> _kv;
AVLTreeNode<K, V>* _left;
AVLTreeNode<K, V>* _right;
AVLTreeNode<K, V>* _parent;
int _bf;
AVLTreeNode(const pair<K, V>& kv)
:_kv(kv)
,_left(nullptr)
,_right(nullptr)
,_parent(nullptr)
,_bf(0)
{}
};
template<class K,class V>
class AVLTree
{
typedef AVLTreeNode<K, V> Node;
public:
bool Insert(const pair<K, V>& kv)
{
if (_root == nullptr)
{
_root = new Node(kv);
return true;
}
Node* parent = nullptr;
Node* cur = _root;
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 < cur->_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;
}
else if (parent->_bf == 1 || parent->_bf == -1)
{
cur = parent;
parent = parent->_parent;
}
else if (parent->_bf == 2 || parent->_bf == -2)
{
if (parent->_bf == 2 && cur->_bf == 1)
{
RotateL(parent);
}
else if (parent->_bf == -2 && cur->_bf == -1)
{
RotateR(parent);
}
else if (parent->_bf == -2 && cur->_bf == 1)
{
RotateLR(parent);
}
else if (parent->_bf == 2 && cur->_bf == -1)
{
RotateRL(parent);
}
break;
}
else assert(false);
}
return true;
}
void RotateL(Node* parent)
{
++_rotateCount;
Node* cur = parent->_right;
Node* curleft = cur->_left;
parent->_right = curleft;
if (curleft)
{
curleft->_parent = parent;
}
cur->_left = parent;
Node* ppnode = parent->_parent;
parent->_parent = cur;
if (parent == _root)
{
_root = cur;
cur->_parent = nullptr;
}
else
{
if (ppnode->_left == parent)
{
ppnode->_left = cur;
}
else
{
ppnode->_right = cur;
}
cur->_parent = ppnode;
}
parent->_bf = cur->_bf = 0;
}
void RotateR(Node* parent)
{
++_rotateCount;
Node* cur = parent->_left;
Node* curright = cur->_right;
parent->_left = curright;
if (curright)
curright->_parent = parent;
Node* ppnode = parent->_parent;
cur->_right = parent;
parent->_parent = cur;
if (ppnode == nullptr)
{
_root = cur;
cur->_parent = nullptr;
}
else
{
if (ppnode->_left == parent)
{
ppnode->_left = cur;
}
else
{
ppnode->_right = cur;
}
cur->_parent = ppnode;
}
parent->_bf = cur->_bf = 0;
}
void RotateRL(Node* parent)
{
Node* cur = parent->_right;
Node* curleft = cur->_left;
int bf = curleft->_bf;
RotateR(parent->_right);
RotateL(parent);
if (bf == 0)
{
cur->_bf = 0;
curleft->_bf = 0;
parent->_bf = 0;
}
else if (bf == 1)
{
cur->_bf = 0;
curleft->_bf = 0;
parent->_bf = -1;
}
else if (bf == -1)
{
cur->_bf = 1;
curleft->_bf = 0;
parent->_bf = 0;
}
else
{
assert(false);
}
}
void RotateLR(Node* parent)
{
Node* cur = parent->_left;
Node* curright = cur->_right;
int bf = curright->_bf;
RotateL(parent->_left);
RotateR(parent);
if (bf == 0)
{
parent->_bf = 0;
cur->_bf = 0;
curright->_bf = 0;
}
else if (bf == -1)
{
parent->_bf = 1;
cur->_bf = 0;
curright->_bf = 0;
}
else if (bf == 1)
{
parent->_bf = 0;
cur->_bf = -1;
curright->_bf = 0;
}
}
int Height()
{
return Height(_root);
}
int Height(Node* root)
{
if (root == nullptr)
return 0;
int leftHeight = Height(root->_left);
int rightHeight = Height(root->_right);
return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
}
bool IsBalance()
{
return IsBalance(_root);
}
bool IsBalance(Node* root)
{
if (root == nullptr)
return true;
int leftHight = Height(root->_left);
int rightHight = Height(root->_right);
if (rightHight - leftHight != root->_bf)
{
cout << "平衡因子异常:" << root->_kv.first << "->" << root->_bf << endl;
return false;
}
return abs(rightHight - leftHight) < 2
&& IsBalance(root->_left)
&& IsBalance(root->_right);
}
private:
Node* _root = nullptr;
public:
int _rotateCount = 0;
};
void TestAVLTree()
{
AVLTree<int, int> t;
int a[] = { 4, 2, 6, 1, 3, 5, 7 };
for (auto e : a)
{
t.Insert(make_pair(e, e));
}
cout << "IsBalance: " << t.IsBalance() << endl;
cout << "Height: " << t.Height() << endl;
cout << "RotateCount: " << t._rotateCount << endl;
}
int main()
{
TestAVLTree();
return 0;
}