前言:
前个屁言好好复习(ノ`Д)ノ(ノ`Д)ノ
一、AVL树的右单旋转
上图在插入前,AVL树是平衡的,新节点插入到30的左子树(注意:此处不是左孩子)中,30左子树增加了一层,导致以60为根的二叉树不平衡,要让60平衡,只能将60左子树的高度减少一层,右子树增加一层,即将左子树往上提,这样60转下来,因为60比30大,只能将其放在30的右子树,而如果30有右子树,右子树根的值一定大于30,小于60,只能将其放在60的左子树,旋转完成后,更新节点的平衡因子即可。在旋转过程中,有以下几种情况需要考虑:
- 30节点的右孩子可能存在,也可能不存在
- 60可能是根节点,也可能是子树
- 如果是根节点,旋转完成后,要更新根节点
- 如果是子树,可能是某个节点的左子树,也可能是右子树
1.1代码实现
void RotateR(Node* parent)
{
Node* cur = parent->_left;
Node* curRight = cur->_right;
parent->_left = curRight;
cur->_right = parent;
Node* ppNode = parent->_parent;
if (curRight)//右孩子可能存在,也可能不存在,所以需要判断,需要在parent改变前判断
{
curRight->_parent = parent;
}
parent->_parent = cur;
if (parent == _root)//parent可能是根节点,也可能不是根节点
{
_root = cur;
cur->_parent = nullptr;
}
else
{
if (ppNode->_left == parent)
{
ppNode->_left = cur;
}
else
{
ppNode->_right = cur;
}
cur->_parent = ppNode;
}
cur->_bf = parent->_bf = 0;//将平衡因子调整
}
二、AVL树的左单旋转
- 新节点插入较高右子树的右侧—右右:左单旋
这里进行参考右单旋转就可理解
注:如果是左单旋转parent的平衡因子应该是2,cur的平衡因子应该是1
如果是右单旋转parent的平衡因子应该是-2,cur的平衡因子应该是-1。
三、AVL树的左右单旋
新节点插入较高左子树的右侧—左右:先左单旋再右单旋
即:先对30进行左单旋,然后再对90进行右单旋,旋转完成后再考虑平衡因子的更新。
注:平衡因子的更新分为三种情况
1.当h是为0的时候,进行左右双旋,那么它的平衡因子都是为0的。
2.当h>0的时候,进行左右双旋,那么它的平衡因子修改分为两种情况
(1)当插入节点在b的位置,如图所示,30节点的平衡因子修改为0,60节点的平衡因子修改为090节点的平衡因子修改为1
(2)当擦汗如节点在c的位置,将上图的紫色方框放到c的位置,那么60和90节点的平衡因子为0,30节点的平衡因子为-1.这个平衡因子的修改是根据目录AVL树的定义的方式修改的。
3.1代码实现 :
void RotateLR(Node* parent)
{
Node* cur = parent->_left;
Node* curRight = cur->_right;
int bf = curRight->_bf;
//复用左单旋转和右单旋转
RotateL(cur);
RotateR(parent);
if (bf == 0)
{
parent->_bf = 0;
cur->_bf = 0;
curRight->_bf = 0;
}
else if (bf == -1)//curRight的左树插入新节点
{
parent->_bf = 1;
cur->_bf = 0;
curRight->_bf = 0;
}
else if (bf == 1)//curRight的右树插入新节点
{
cur->_bf = -1;
parent->_bf = 0;
curRight->_bf = 0;
}
else//不可能出现此情况,如果出现就是出错
{
assert(false);
}
}
四、AVL树的右左单旋
- 新节点插入较高右子树的左侧—右左:先右单旋再左单旋
4.1代码实现
void RotateRL(Node* parent)
{
Node* cur = parent->_right;
Node* curleft = cur->_left;
int bf = curleft->_bf;
//复用右单旋转和左单旋转
RotateR(cur);
RotateL(parent);
if (bf == 0)
{
parent->_bf = 0;
cur->_bf = 0;
curleft->_bf = 0;
}
else if (bf == 1)//curLeft的右树插入新节点
{
parent->_bf = -1;
cur->_bf = 0;
curleft->_bf = 0;
}
else if(bf == -1)//curLeft的左树插入新节点
{
cur->_bf = 1;
parent->_bf = 0;
curleft->_bf = 0;
}
else
{
assert(false);
}
}
后记:
慢慢肝咯,好好学习天天向上