一.概念
最小不平衡子树:距离插入结点最近的,且平衡因子的绝对值大于1的结点为根的子树
二.实现原理
基本思想:在构建二叉排序树时,每当插入一个结点时,先检查是否因插入而破坏了树的平衡性,若是,则找出最小不平衡子树。在保持二叉排序树特性的前提下,调整最小不平衡子树中各结点之间的链接关系,进行相应的旋转,使之成为新的平衡子树。
1.BF为负时向左转,为正向右转
2.转向之前要确保最小不平衡子树的根结点与它的子结点符号是相同的 同正负再调向
举个例子
对于一个给定的数组 [3, 2, 1, 4, 5, 6, 7, 10, 9, 8]
在这棵树中可以看到只有根节点 2 是不平衡的,且 BF = -2 < 0,所以需要将根节点 2 向左旋转,得到如下的结果
由于 3 小于 4 ,所以将 3 连接在 4 的左子树的最右端,得到如下图所示的结果
添加9
但是这个结点不可以像之前一样通过旋转 7 10 9 这棵子树,因为这个时候, 10 结点的 BF 符号与之前的符号均不相同,所以要首先将 9 10 旋转,之后再将不平衡子树进行旋转,如下图所示
添加8
明显结点 4 的 BF 为正,结点 6 的 BF 为正,但是结点 9 的 BF 为负,这个时候应该先将 8 7 9 10 进行旋转,使得 BF 值相等,然后再调整二叉排序树,如下图所示
三.不平衡因子的四种情况
1.单向右旋平衡处理:若由于结点 a 的左子树为根结点的左子树上插入结点,导致结点 a 的平衡因子由 1 增至 2,致使以 a 为根结点的子树失去平衡,则只需进行一次向右的顺时针旋转,如下图这种情况
2.单向左旋平衡处理:如果由于结点 a 的右子树为根结点的右子树上插入结点,导致结点 a 的平衡因子由 -1变为 -2,则以 a 为根结点的子树需要进行一次向左的逆时针旋转,如下图这种情况:
3.双向旋转(先左后右)平衡处理:如果由于结点 a 的左子树为根结点的右子树上插入结点,导致结点 a 平衡因子由 1 增至 2,致使以 a 为根结点的子树失去平衡,则需要进行两次旋转操作,如下图这种情况:
4.双向旋转(先右后左)平衡处理:如果由于结点 a 的右子树为根结点的左子树上插入结点,导致结点 a 平衡因子由 -1 变为 -2,致使以 a 为根结点的子树失去平衡,则需要进行两次旋转(先右旋后左旋)操作,如下图这种情况:
四.构建平衡二叉树的代码实现
1.结点结构
typedef struct BiTNode{
int data;
int BF;
struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;
2.左右旋操作
void L_Rotate(BiTree *p)
{
BiTree L;
L = (*p) -> rchild;
(*p) -> rchild = L -> lchild;
L -> lchild = (*p);
*p = L;
}
void R_Rotate(BiTree *p)
{
BiTree L;
L = (*p) -> lchild;
(*p) -> lchild = L -> rchild;
L -> rchild = (*p);
*p = L;
}
3.左右平衡旋转处理
void LeftBalance(BiTree *T)
{
BiTree L, Lr;
L = (*T) -> lchild;
switch(L -> BF)
{
case LH:
{
(*T) -> BF = L -> BF = EH;
R_Rotate(T);
break;
}
case RH:
{
Lr = L -> rchild;
switch(Lr -> BF)
{
case LH:
{
(*T) -> BF = RH;
L -> BF = EH;
break;
}
case EH:
{
(*T) -> BF = L -> BF = EH;
break;
}
case RH:
{
(*T) -> BF = EH;
L -> BF = LH;
break;
}
}
Lr -> BF = EH;
L_Rotate(&(*T) -> lchild);
R_Rotate(T);
}
}
}
void RightBalance(BiTree *T)
{
BiTree L, Lr;
L = (*T) -> rchild;
switch(L -> BF)
{
case RH:
{
(*T) -> BF = L -> BF = EH;
L_Rotate(T);
break;
}
case LH:
{
Lr = L -> lchild;
switch(Lr -> BF)
{
case LH:
{
(*T) -> BF = EH;
L -> BF = RH;
break;
}
case EH:
{
(*T) -> BF = L -> BF = EH;
break;
}
case RH:
{
(*T) -> BF = EH;
L -> BF = LH;
break;
}
}
Lr -> BF = EH;
R_Rotate(&(*T) -> rchild);
L_Rotate(T);
}
}
}
4.二叉树的主函数
int InsertAVL(BiTree *T, int e, int *taller)
{
if(!*T)
{
*T = (BiTree)malloc(sizeof(BiTNode));
(*T) -> data = e;
(*T) -> lchild = (*T) -> rchild = NULL;
(*T) -> BF = EH;
*taller = TRUE;
}
else
{
if(e == (*T) -> data)
{
*taller = FALSE;
return FALSE;
}
if(e < (*T) -> data) //应继续在T的左子树中进行搜索
{
if(! InsertAVL(&(*T) -> lchild, e, taller))
{
return FALSE;
}
if(*taller) //已经插入到T的左子树里且左子树"长高"
{
switch((*T) -> BF)
{
case LH:
{
LeftBalance(T);
*taller = FALSE;
break;
}
case EH: //原本左右子树等高,现在左子树增高而树增高
{
(*T) -> BF = LH;
*taller = TRUE;
break;
}
case RH:
{
(*T) -> BF = EH;
*taller = FALSE;
break;
}
}
}
}
else
{
if(! InsertAVL(&(*T) -> rchild, e, taller))
{
return FALSE;
}
if(*taller)
{
switch((*T) -> BF)
{
case LH:
{
(*T) -> BF = EH;
*taller = FALSE;
break;
}
case EH:
{
(*T) -> BF = RH;
*taller = TRUE;
break;
}
case RH:
{
RightBalance(T);
*taller = FALSE;
break;
}
}
}
}
}
return TRUE;
}