一 . 性质
一棵AVL树或者是空树,或者是具有以下性质的二叉搜索树:
1 . 它的左右子树都是AVL树
2 . 左右子树高度之差(简称平衡因子)的绝对值不超过1(-1/0/1)
(下面代码的高度之差:右树高度 - 左树高度)
二 . 模拟实现(只实现插入insert)
1.先把二叉搜索树的插入代码补上。
区别在于多了_parent,_bf
template<class K, class V>
struct AVLTreeNode
{
AVLTreeNode<K, V>* _left;
AVLTreeNode<K, V>* _right;
AVLTreeNode<K, V>* _parent;
pair<K, V> _kv;
int _bf; //右子树高度 - 左子树高度
AVLTreeNode(const pair<K, V>& kv)
:_left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _kv(kv)
, _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* cur = _root;
Node* parent = nullptr;
//先找到合适位置插入
while (cur)
{
if (cur->_kv.first > kv.first)
{
parent = cur;
cur = cur->_left;
}
else if (cur->_kv.first < kv.first)
{
parent = cur;
cur = cur->_right;
}
else
{
return false;
}
}
//插入
cur = new Node(kv);
if (parent->_kv.first > kv.first)
{
parent->_left = cur;
cur->_parent = parent;
}
else
{
parent->_right = cur;
cur->_parent = parent;
}
//调整树,使二叉搜索树成为AVL树(从parent开始向上)
return true;
}
private:
Node* _root;
}
2. 如果新增节点在左子树,父节点bf--
在右子树,父节点bf++。
(1)更新后,父亲bf == 0,不用再向上调整
(2)父亲bf == 1 || -1,需要向上继续调整bf值
(3)父亲bf == 2 || -2,需要旋转树重新构成AVL树
//调整树,使二叉搜索树成为AVL树(从parent开始向上)
//调整bf值(从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)
{
//旋转
}
else
{
assert(false);
}
}
3 . 通过旋转使其成为AVL树,最后改变bf值
总共有四种情况
完整代码
#pragma once
template<class K, class V>
struct AVLTreeNode
{
AVLTreeNode<K, V>* _left;
AVLTreeNode<K, V>* _right;
AVLTreeNode<K, V>* _parent;
pair<K, V> _kv;
int _bf;
AVLTreeNode(const pair<K, V>& kv)
:_left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _kv(kv)
, _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* cur = _root;
Node* parent = nullptr;
//先找到合适位置插入
while (cur)
{
if (cur->_kv.first > kv.first)
{
parent = cur;
cur = cur->_left;
}
else if (cur->_kv.first < kv.first)
{
parent = cur;
cur = cur->_right;
}
else
{
return false;
}
}
//插入
cur = new Node(kv);
if (parent->_kv.first > kv.first)
{
parent->_left = cur;
cur->_parent = parent;
}
else
{
parent->_right = cur;
cur->_parent = parent;
}
//调整bf值(从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 (cur->_bf == 1 && parent->_bf == 2)
{
RotateL(parent);
}
else if (cur->_bf == -1 && parent->_bf == -2)
{
RotateR(parent);
}
else if (parent->_bf == 2 && cur->_bf == -1)
{
RotateRL(parent);
}
else if (parent->_bf == -2 && 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;
subR->_left = parent;
Node* pp = parent->_parent;
//subR->_parent = pp;
parent->_parent = subR;
if (subRL != nullptr) subRL->_parent = parent;
if (_root == parent)
{
_root = subR;
subR->_parent = nullptr;
}
else
{
if (pp->_left == parent)
pp->_left = subR;
else
pp->_right = subR;
subR->_parent = pp;
}
parent->_bf = subR->_bf = 0;
}
void RotateR(Node* parent)//左左:右单旋
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
parent->_left = subLR;
if (subLR != nullptr) subLR->_parent = parent;
Node* pp = parent->_parent;
subL->_right = parent;
parent->_parent = subL;
if (_root == parent)
{
_root = subL;
subL->_parent = nullptr;
}
else
{
if (pp->_left == parent)
pp->_left = subL;
else
pp->_right = subL;
subL->_parent = pp;
}
parent->_bf = subL->_bf = 0;
}
void RotateRL(Node* parent)//右+左
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
int bf = subRL->_bf;
RotateR(parent->_right);
RotateL(parent);
//修改bf
if (bf == 0)//subRL自己是新增的
{
parent->_bf = subR->_bf = subRL->_bf = 0;
}
else if (bf == -1)//左子树下insert
{
parent->_bf = 0;
subRL->_bf = 0;
subR->_bf = 1;
}
else if (bf == 1)//右子树下insert
{
parent->_bf = -1;
subRL->_bf = 0;
subR->_bf = 0;
}
else
{
assert(false);
}
}
void RotateLR(Node* parent)//左+右
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
int bf = subLR->_bf;
RotateL(parent->_left);
RotateR(parent);
if (bf == 0)
{
parent->_bf = 0;
subLR->_bf = 0;
subL->_bf = 0;
}
else if (bf == -1)//b下
{
parent->_bf = 1;
subLR->_bf = 0;
subL->_bf = 0;
}
else if (bf == 1)
{
parent->_bf = 0;
subLR->_bf = 0;
subL->_bf = -1;
}
else
{
assert(false);
}
}
//用来判断树是否是AVL树
bool isbalance()
{
return _isbalance(_root);
}
bool _isbalance(Node* root)
{
if (root == nullptr) return true;
int leftH = _height(root->_left);
int rightH = _height(root->_right);
if (rightH - leftH != root->_bf)
{
cout << root->_kv.first << "平衡因子error" << endl;
return false;
}
return abs(rightH - leftH) < 2
&& _isbalance(root->_left) \
&& _isbalance(root->_right);
}
int _height(Node* root)
{
if (root == nullptr) return 0;
int leftH = _height(root->_left);
int rightH = _height(root->_right);
return leftH > rightH ? leftH + 1 : rightH + 1;
}
void Inorder()
{
_Inorder(_root);
cout << endl;
}
void _Inorder(Node* root)
{
if (root == nullptr) return;
_Inorder(root->_left);
cout << root->_kv.first << "(" << root->_bf << ")" << "_";
_Inorder(root->_right);
}
private:
Node* _root = nullptr;
};