AVL树的概念
一棵AVL树或者是空树,或者是具有以下性质的二叉搜索树:
它的左右子树都是AVL树
左右子树高度之差(简称平衡因子)的绝对值不超过1(-1/0/1)
如果一棵二叉搜索树是高度平衡的,它就是AVL树。如果它有n个结点,其高度可保持在
O ( l o g 2 n ) O(log_2 n) O(log2n),搜索时间复杂度O( l o g 2 n log_2 n log2n)。
AVL树节点的定义
template<class Key,class Val>
struct AVLTreeNode
{
AVLTreeNode<Key, Val>* _left;
AVLTreeNode<Key, Val>* _right;
AVLTreeNode<Key, Val>* _parent;
pair<Key, Val> _kv;
//平衡因子
int _bf;
AVLTreeNode(const pair<Key, Val>& kv)
:_left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _kv(kv)
,_bf(0)
{}
};
AVL树的插入(难点)
AVL树就是在二叉搜索树的基础上引入了平衡因子,因此AVL树也可以看成是二叉搜索树。那么AVL树的插入过程可以分为两步:
- 按照二叉搜索树的方式插入新节点
搜索二叉树 - 调整节点的平衡因子
情况1:新节点插入较高左子树的左侧-进行右单旋
void RotateR(Node* cur)
{
Node* SubL = cur->_left;
Node* SubLR = SubL->_right;
// 60
// 30
//10
Node* parent = cur->_parent;
cur->_left = SubLR;
if(SubLR)
SubLR->_parent = cur;
SubL->_right = cur;
cur->_parent = SubL;
if (parent == nullptr)
{
_root = SubL;
SubL->_parent = parent;
}
else
{
if (parent->_left == cur)
{
parent->_left = SubL;
SubL->_parent = parent;
}
else if (parent->_right == cur)
{
parent->_right = SubL;
SubL->_parent = parent;
}
else
{
assert(false);
}
}
}
情况2:新节点插入较高右子树的右侧-进行左单旋
void RotateL(Node* cur)
{
Node* SubR = cur->_right;
Node* SubRL = SubR->_left;
//10
// 30
// 60
Node* parent = cur->_parent;
cur->_right = SubRL;
if (SubRL)
SubRL ->_parent = cur;
SubR->_left = cur;
cur->_parent = SubR;
if (parent == nullptr)
{
_root = SubR;
SubR->_parent = parent;
}
else
{
if (parent->_left == cur)
{
parent->_left = SubR;
SubR->_parent = parent;
}
else if (parent->_right == cur)
{
parent->_right = SubR;
SubR->_parent = parent;
}
else
{
assert(false);
}
}
}
情况三: 新节点插入较高左子树的右侧-先左单旋再右单旋
1.在b树插入新节点
2.在c树插入新节点
3.60即为插入的新节点
以上三种情况都是先左旋再右旋,区别:旋转完之后节点的平衡因子不同
Node* node = cur->_right;
int bf = node->_bf;
RotateL(cur);
RotateR(parent);
if (bf == 0)
{
parent->_bf = cur->_bf = node->_bf = 0;
}
else if (bf == -1)
{
cur->_bf = node->_bf = 0;
parent->_bf = 1;
}
else if (bf == 1)
{
parent->_bf = node->_bf = 0;
cur->_bf = -1;
}
情况4:新节点插入较高右子树的左侧-先右单旋再左单旋
与情况三相同,60的平衡因子会影响旋转完之后30 60 90 的平衡因子
Node* node = cur->_left;
int bf = node->_bf;
RotateR(cur);
RotateL(parent);
if (bf == 0)
{
parent->_bf = cur->_bf = node->_bf = 0;
}
else if (bf == 1)
{
cur->_bf = node->_bf = 0;
parent->_bf = -1;
}
else if (bf == -1)
{
node->_bf = parent->_bf = 0;
cur->_bf = 1;
}