第一种旋转方式是LL类型,如图所示:
k2的左边比右边高了2,说明X的高度比Z高1
代码如下
void LL_Rotate(AVLNode* &p)
{
AVLNode * lc = NULL;
lc = p->lchild; //lc指向p的左子树根结点
p->lchild = lc->rchild; //lc的右子树挂接为p的左子树
lc->rchild = p;
p = lc; //p指向新的根结点
}
思路就是把k1放在根结点,然后把k1的右子树Y挂在k2上,k2挂在k1右边。
平衡因子改变:如果Y和X等高,那么k1平衡因子为-1,k2平衡因子为1,如果X比Y高,那么k1和k2平衡因子都为0。
第二种旋转方式为LR旋转,如图所示:
其中B和C至少有一个和D是一样高(图中取了平均)。LR旋转的本质是先进行一次RR旋转变成LL类型的树,然后再进行一次LL旋转。代码如下所示:
void LR_Rotate(AVLNode* &p)
{
RR_Rotate(p->lchild);
LL_Rotate(p);
}
平衡因子调整:如果B比C高,那么B和A是一样高的,那么k1平衡因子为0,k3平衡因子为-1.同理,如果C比B高,那么k3平衡因子为0,k1平衡因子为-1.如果B和C一样高,那么k1和k2的平衡因子都为0。k3恒为0。
根据LL旋转和LR旋转就可以写出AVL树的左边平衡代码了:
void leftBalance(AVLNode* &t)
{
AVLNode* lc = NULL;
AVLNode* rd = NULL;
lc = t->lchild;
switch(lc->bf)
{
case LH: //LL旋转
t->bf = EH;
lc->bf = EH;
LR_Rotate(t);
break;
case EH: //deleteAVL需要,insertAVL用不着
t->bf = LH;
lc->bf = RH;
LR_Rotate(t);
break;
case RH: //LR旋转
rd = lc->rchild;
switch(rd->bf)
{
case LH:
t->bf = RH;
lc->bf = EH;
break;
case EH:
t->bf = EH;
lc->bf = EH;
break;
case RH:
t->bf = EH;
lc->bf = LH;
break;
}
rd->bf = EH;
LR_Rotate(t);
break;
}
}
第三种旋转方式为RR旋转
分析方法和LL旋转一样,代码如下
void RR_Rotate(AVLNode* &p)
{
AVLNode * rc = NULL;
rc = p->rchild; //rc指向p的右子树根结点
p->rchild = rc->lchild;//rc的左子树挂接为p的右子树
rc->lchild = p;
p = rc; //p指向新的根结
第四种方式是RL旋转,如图所示:
分析方式和LR旋转类似,平衡因子也要看BC和A的高度情况。
代码如下:
void RL_Rotate(AVLNode* &p)
{
LL_Rotate(p->rchild);
RR_Rotate(p);
}
由此可以写出右平衡代码
void rightBalance(AVLNode* &t)
{
AVLNode* rc = NULL;
AVLNode *ld = NULL;
rc = t->rchild;
switch(rc->bf)
{
case LH: //RL旋转
ld = rc->lchild;
switch(ld->bf)
{
case LH:
t->bf = EH;
rc->bf = RH;
break;
case EH:
t->bf = EH;
rc->bf = EH;
break;
case RH:
t->bf = LH;
rc->bf = EH;
break;
}
ld->bf = EH;
RL_Rotate(t);
break;
case EH: //deleteAVL需要,insertAVL用不着
t->bf = RH;
rc->bf = LH;
L_Rotate(t);
break;
case RH: //RR旋转
t->bf = EH;
rc->bf = EH;
RR_Rotate(t);
break;
}
}
本文代码参考了:http://blog.csdn.net/sysu_arui/article/details/7897017