1.基本介绍
平衡二叉树是一种特殊的二叉查找树,其左右子树都是平衡二叉树,且高度差的绝对值不超过1
如何使二叉查找树在添加数据的同时保持平衡呢?基本思想就是:当在二叉排序树中插入一个节点时,首先检查是否因插入而破坏了平衡,若破坏,则找出其中的最小不平衡二叉树,在保持二叉排序树特性的情况下,调整最小不平衡子树中节点之间的关系,以达到新的平衡。所谓最小不平衡子树 指离插入节点最近且以平衡因子的绝对值大于1的节点作为根的子树。
插入操作下的四种平衡旋转情况:
1)绕某元素左旋转
对于一颗右子树高于左子树的平衡二叉树,当右子树的右子树插入了新的节点,平衡性被打破,则需要进行左旋,如下图
2)绕某元素右旋转
对于一颗左子树高于右子树的平衡二叉树,当左子树的左子树插入了新的节点,平衡被打破,则需要进行右旋,如下图
3)绕某元素的左子节点左旋转,再绕该元素进行右旋转
对于一颗左子树高于右子树的平衡二叉树,当左子树的右子树插入了新的节点,平衡被打破,需要先绕左子树的根节点进行左旋,再绕根节点进行右旋,如下图
4)绕某元素的右子节点右旋转,再绕该元素进行左旋转
对于一颗右子树高于左子树的平衡二叉树,当右子树的左子树插入了新的节点,平衡被打破,需要先绕右子树的根节点进行右旋,再绕根节点进行左旋,如下图
2.实现的C语言代码
#define LH 1
#define EH 0
#define RH -1
typedef struct TreeNode{
int data;
int bf;
struct TreeNode* left=null;
struct TreeNode* right=null;
}TreeNode,BiTree*;
//插入成功返回1,否则返回0
//树长高taller=1,否则taller=0
int InsertAVL(BiTree* T,int e,int* taller){
if(!*T){
*T=(BiTree)malloc(sizeof(TreeNode));
(*T)->data=e;
(*T)->bf=0;
(*T)->left=(*T)->right=null;
}else{
if(e==(*T)->data){
return 0;
}
if(e<(*T)->data){
if(!InsertAVL(&(*T)->left,e,taller)){
return 0;
}
if(taller){
switch((*T)->bf){
case LH:
LeftBalance(T);
*taller=0;
break;
case EH:
(*T)->bf=LH;
*taller=1;
break;
case RH:
(*T)->bf=EH;
*taller=0;
break;
}
}
}else{
if(!InsertAVL(&(*T)->right,e,taller)){
return 0;
}
if(taller){
switch((*T)->bf){
case LH:
(*T)bf=EH;
*taller=0;
break;
case EH:
(*T)bf=RH;
*taller=1;
break;
case RH:
RightBalance(T);
*taller=0;
break;
}
}
}
}
return 1;
}
void LeftBalance(BiTree* T){
TreeNode L,Lr;
L=(*T)->left;
switch(L->bf){
case LH:
(*T)->bf=L->bf=EH;
R_Rotate(T);
break;
case RH:
Lr=L->right;
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)->left);
R_Rotate(T);
}
}
void RightBalance(BiTree* T){
TreeNode R,Rl;
R=(*T)->right;
switch(R->bf){
case LH:
Rl=R->left;
switch(Rl->bf){
case LH:
(*T)->bf=EH;
R->bf=RH;
break;
case EH:
(*T)->bf=R->bf=EH;
break;
case RH:
(*T)->bf=LH;
R->bf=EH;
break;
}
Rl->bf=EH;
R_Rotate(&(*T)->right);
L_Rotate(T);
break;
case RH:
(*T)->bf=R->bf=EH;
L_Rotate(T);
}
}
void L_Rotate(BiTree* T){
BiTree R=(*T)->right;
(*T)->right=R->left;
R->right=(*T);
(*T)=R;
}
void R_Rotate(BiTree* T){
BiTree L=(*T)->left;
(*T)->left=L->right;
L->right=(*T);
(*T)=L;
}