一、旋转
总体原则:
左旋:变成右孩子的左节点
右旋:变成左孩子的右节点
二、C实现代码
void R_Rotate(BSTree *T)
{
BSTree lc;
lc = (*T)->lchild;
(*T)->lchild = lc->rchild;
lc->rchild = (*T);
(*T) = lc;
return;
}
void L_Rotate(BSTree *T)
{
BSTree rc;
rc = (*T)->rchild;
(*T)->rchild = rc->lchild;
rc->lchild = (*T);
(*T) = rc;
return;
}
void LeftBalance(BSTree *T)
{
BSTree lc;
BSTree rd;
lc = (*T)->lchild;
switch (lc->bf)
{
case 1:
(*T)->bf = lc->bf = 0;
R_Rotate(T);
break;
case -1:
rd = lc->rchild;
switch (rd->bf)
{
case 1:
lc->bf = 0;
(*T)->bf = -1;
break;
case 0: /* 此处比较特殊,如果ABC构成LR图形,A没有右子树,就会造成这里rd的平衡因子为0的情况,RightBalance类似 */
lc->bf = (*T)->bf = 0;
break;
case -1:
lc->bf = 1;
(*T)->bf = 0;
break;
default:
break;
}
rd->bf = 0;
L_Rotate(&lc);
R_Rotate(T);
default:
break;
}
}
void RightBalance(BSTree *T)
{
BSTree rc;
BSTree ld;
rc = (*T)->rchild;
switch (rc->bf)
{
case -1:
(*T)->bf = rc->bf = 0;
L_Rotate(T);
break;
case 1:
ld = rc->lchild;
switch (ld->bf)
{
case 1:
rc->bf = -1;
(*T)->bf = 0;
break;
case 0:
rc->bf = (*T)->bf = 0;
break;
case -1:
rc->bf = 0;
(*T)->bf = 1;
break;
default:
break;
}
ld->bf = 0;
R_Rotate(&rc);
L_Rotate(T);
default:
break;
}
}
Status InsertAVL(BSTree *T, ElemType e, Boolean *taller)
{
if (!*T)
{
(*T) = (BSTree)malloc(sizeof(BSTNode));
if (!(*T))
{
printf("%s: malloc fail\n", __FUNCTION__);
return ERROR;
}
(*T)->data = e;
(*T)->lchild = (*T)->rchild = NULL;
(*T)->bf = 0;
*taller = TRUE;
}
else
{
if (e == (*T)->data)
{
printf("%s: AVL exits the node with key=%d\n", __FUNCTION__, e);
return FAIL;
}
else if (e < (*T)->data)
{
if (SUCCESS != InsertAVL(&(*T)->lchild, e, taller))
{
return FAIL;
}
if (*taller) /* 此处和上个if不是if else关系 */
{
switch ((*T)->bf)
{
case 1:
LeftBalance(T);
*taller = FALSE;
break;
case 0:
(*T)->bf = 1;
*taller = TRUE;
break;
case -1:
(*T)->bf = 0;
*taller = FALSE;
break;
default:
break;
}
}
}
else
{
if (SUCCESS != InsertAVL(&(*T)->rchild, e, taller))
{
return FAIL;
}
if (*taller)
{
switch ((*T)->bf)
{
case -1:
RightBalance(T);
*taller = FALSE;
break;
case 0:
(*T)->bf = -1;
*taller = TRUE;
break;
case 1:
(*T)->bf = 0;
*taller = FALSE;
break;
default:
break;
}
}
}
}
return SUCCESS; /* 一定要有返回值 */
}