AVL树的定义:一棵树中的所有子树的高度差都不能超过 1
。
AVLTree.h
#pragma once
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平衡因子 = 右树高度 - 左树高度
//AVL树的判定方法:一棵树中有没有平衡因子超过了 1
//AVL树没有规定一定要使用平衡因子,也可以设定为高度,现场计算
AVLTreeNode(const pair<K, V>& kv)
:_kv(kv)
, _left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _bf(0) //所有新创建的平衡因子是 0
{} //一个数的平衡因子只受其 孩子 的影响,不受其自身影响。
}; //而它影响了直系祖先结点
template<class K, class V>
class AVLTree{
typedef AVLTreeNode<K, V> Node;
public:
//新增在左,父亲平衡因子 -1
//新增在右,父亲平衡因子 +1
//持续网祖先更新,祖先bf == 0,则祖先的子树高度不变,停止向上更新
//祖先|bf| == 1,则祖先所在的子树的高度变化(肯定是由0变化过来的),继续向上更新
//祖先|bf| == 2,则祖先所在的子树的高度不平衡,开始旋转
bool Insert(const pair<K, V>& kv){
// 1. 插入节点
if (_root == nullptr){
_root = new Node(kv);
_root->_bf = 0;
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 < kv.first){ //三叉链
parent->_right = cur;
cur->_parent = parent;
}
else{
parent->_left = cur;
cur->_parent = parent;
}
/*如果是搜索树,此时就可以 return true了 */
// 2. 调平衡
// 2.1.更新平衡因子
while (parent){
if (cur == parent->_right){
parent->_bf++;
}
else{
parent->_bf--;
}
if (parent->_bf == 0){ // 高度不变,更新完成
break;
}
else if (abs(parent->_bf) == 1){ // 高度变了,继续完成
cur = parent;
parent = parent->_parent;
}
else if (abs(parent->_bf) == 2){ // 不平衡,旋转
if (parent->_bf == 2){
if (cur->_bf == 1){
RotateL(parent);
}
else if (cur->_bf == -1){
RotateRL(parent);
}
}
else if (parent->_bf == -2){
if (cur->_bf == -1){
RotateR(parent);
}
else if (cur->_bf == 1){
RotateLR(parent);
}
}
break;
}
else{
assert(false); //不允许逻辑执行到此,到达说明插入之前就已经不平衡了
}
}
return true;
}
//左单旋
void RotateL(Node* parent){
Node* subR = parent->_right;
Node* subRL = subR->_left;
parent->_right = subRL;
if (subRL)
subRL->_parent = parent;
subR->_left = parent;
Node* ppNode = parent->_parent;
parent->_parent = subR;
if (parent == _root){
_root = subR;
_root->_parent = nullptr;
}
else{
if (ppNode->_left == parent)
ppNode->_left = subR;
else
ppNode->_right = subR;
subR->_parent = ppNode;
}
parent->_bf = subR->_bf = 0;
}
//右单旋
void RotateR(Node* parent){
Node* subL = parent->_left; //左孩子
Node* subLR = subL->_right; //左孩子的右孩子
parent->_left = subLR;
if (subLR)
subLR->_parent = parent;
subL->_right = parent;
Node* ppNode = parent->_parent; //parent结点还有祖先结点
parent->_parent = subL;
if (ppNode == nullptr){ //parent就是原树的根
_root = subL;
_root->_parent = nullptr;
}
else{
if (ppNode->_left == parent){
ppNode->_left = subL;
}
else{
ppNode->_right = subL;
}
subL->_parent = ppNode;
}
parent->_bf = subL->_bf = 0;
}
//先左后右双旋
void RotateLR(Node* parent){
RotateL(parent->_left);
RotateR(parent);
}
//先右后左双旋
void RotateRL(Node* parent){
Node* subR = parent->_right;
Node* subRL = subR->_left;
int bf = subRL->_bf; //保存subRL的平衡因子,因为在下面两行会置 0
RotateR(parent->_right);
RotateL(parent);
if (bf == 0){
parent->_bf = subRL->_bf = subR->_bf = 0;
}
else if (bf == 1){ //在c插入的新结点
subR->_bf = 0;
parent->_bf = -1;
subRL->_bf = 0;
}
else if (bf == -1){ //在b插入的新结点
parent->_bf = 0;
subR->_bf = 1;
subRL->_bf = 0;
}
}
void InOrder(){
_InOrder(_root);
cout << endl;
}
void _InOrder(Node* root){
if (root == nullptr)
return;
_InOrder(root->_left);
cout << root->_kv.first << " ";
_InOrder(root->_right);
}
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(){ //this指针是隐含的,所以需要封装
return _IsBalance(_root);
}
bool _IsBalance(Node* root){
if (root == nullptr)
return true;
int leftheight = _Height(root->_left);
int rightheight = _Height(root->_right);
if (rightheight-leftheight != root->_bf){
cout << root->_kv.first << "平衡因子异常" << endl;
return false;
}
return abs(leftheight - rightheight) < 2
&& _IsBalance(root->_left)
&& _IsBalance(root->_right);
}
private:
Node* _root = nullptr;
};
测试代码
void TestAVLTree(){
AVLTree<int, int> t;
//int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 }; //说明是搜索树
int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };
for (auto e : a){
t.Insert(make_pair(e, e));
}
t.InOrder();
cout << t.IsBalance() << endl;
}