AVL解决二叉搜索树退化成链表,保证左右子树高度不差过1,尽可能接近满二叉树
AVL树的性质:高度差(平衡因子)的绝对值不超过1(-1/0/1)
平衡因子:右子树高度-左子树高度
用平衡因子控制高度
AVL树节点
cpp
class AVLTreeNode
{
pair<K, V>_kv; //key/value
AVLTreeNode<K, V>* _left; // 左
AVLTreeNode<K, V>* _right;// 右
AVLTreeNode<K, V>* _partent;// 父母
int _bf;// 平衡因子
AVLTreeNode(const pair<K,V>& kv)
:_kv(kv)
,_left(nullptr)
,_right(nullptr)
,_parent(nullptr)
,_bf(0)
{}
};
控制逻辑:增加一个新节点cur
parent的bf值-1,在右 ,parent的bf加1
如果parent_bf=0,则不再改变,否则继续向上调整,直到parent为0,或者为cur为根节点时。
如果parent的平衡因子为2或者-2,说明树不平衡,要进行旋转调整。
当左边高时(parent=2,cur=1)
柱子a,b,c表示高度为h的AVL树
cpp
parent->right=cur->left
cur->left=parent
对于左单旋的理解:1.根节点向左转,2.c树高度增加后a树高2,于是把c的父节点当成根节点使得c的高度方向-1,a的树的方向+1,刚好平衡
同时调整平衡因子数量和parent指针
左单旋
cpp
void RotateL(Node* parent)
{
Node* cur = parent->_right; //确定cur
Node* curleft = parent->_left;
parent->_left = curleft;
//当h不为0时
if (curleft)
{
//调整parent指针
curleft->_partent = parent;
}
cur->_left = parent;
//调整新的根节点的parent指针
Node* ppnode = parent->_parent;
parent->_parent = cur;
//根节点特殊情况
if (parent == _root)
{
_root = cur;
cur->_partent = nullptr;
}
else
{
// 确定parent是ppnode的左指针还是右指针
if (ppnode->_left==parent)
{
ppnode->_left = cur;
}
else
{
ppnode_right = cur;
}
cur->_partent = ppnode;
}
parent->_bf = cur->_bf = 0;
}
cpp
void RotateR()
{
void RotateR(Node* parent)
{
Node* cur = parent->_left;
Node* curright = cur->_right;
parent->_left = curright;
cur->_right = parent;
Node* ppnode = parent->_parent;
if (curright)
{
curright->_partent = parent;
}
parent->_parent = cur;
if (ppnode == root)
{
_root = cur;
cur->_partent = nullptr;
}
else
{
if (ppnode->_left == parent)
{
ppnode->_left = cur;
}
else(ppnode->_right == parent)
{
ppnode->_right = cur;
}
}
cur->_bf = parent->_bf = 0;
}
}
双旋:我们发现左右双旋都是在都是a,c树高度发生变化,具体体现在cur和parent的平衡因子都是相差1,而如果在b树发生变化,无论是左边高还是右边高都会产生双旋问题。具体可以分为四种情况,现在以一种情况为例:
如下图是右边高的b树(现为60-b-c子树)发生改变。
从图上来讲是90进行右旋,把高的树的树移到外面,再30进行左旋,构建平衡。
对于父节点为60的树来说,左树成为30节点的右树,右树成为90节点的左树。
所以60的节点的双旋后30,60,90的_bf值不恒为0,30,90节点会受到60的影响。
当60->_bf=1, 30,60,90 =-1 ,0,0
60->_bf=-1, 30,60,90 = 1,0,0
当
左高右高的区别都是60做根节点,且_bf变化是一样的。
左高:先左旋后右旋,右高,先右旋后左旋。
插入代码和旋转代码
cpp
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 < kv.first)
{
parent->_right = cur;
}
else if (parent->_kv.first > kv.first)
{
parent->_left = cur;
}
cur->_parent = parent;
return true;
// 更新节点
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)
{
//右高双旋
RotateRL(parent);
}
else
{
//左高双旋
RotateLR(parent);
}
}
else
{
assert(false);
}
}
return true;
}
void RotateL(Node* parent)
{
Node* cur = parent->_right;
Node* curleft = parent->_left;
parent->_left = 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)
{
Node* cur = parent->_left;
Node* curright = cur->_right;
parent->_left = curright;
cur->_right = parent;
Node* ppnode = parent->_parent;
if (curright)
{
curright->_parent = parent;
}
parent->_parent = cur;
if (ppnode == _root)
{
_root = cur;
cur->_parent = nullptr;
}
else
{
if (ppnode->_left == parent)
{
ppnode->_left = cur;
}
else
{
ppnode->_right = cur;
}
}
cur->_bf = parent->_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 == 1)
{
cur->_right->_bf = 0;
cur->_left->_bf= -1;
}
else if (bf == -1)
{
cur->_right->_bf = 0;
cur->_left->_bf = 1;
}
else
{
;
}
}
void RotateLR(Node* parent)
{
Node* cur = parent->_left;
Node* curright = cur->_right;
int bf = curright->_bf;
RotateL(cur);
RotateR(parent);
if(bf == 1)
{
cur->_right->_bf = 0;
cur->_left->_bf = -1;
}
else if(bf==-1)
{
cur->_right->_bf = 0;
cur->_left->_bf = 1;
}
else
{
;
}
}
检验AVL树
cpp
int Height(Node* root)
{
if (root == nullptr)
return true;
int leftHight = Height(root->_left);
int right = Height(root->_right);
return leftHeight > rightHeight ? leftHeight + 1 : rightHeigth + 1;
}
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<<"平衡因子异常"
}
return abs(rightHight - leftHight) < 2
&& IsBalance(root->_left)
&& IsBalance(root->_right);
}