下面讲解AVL树的C语言代码实现:
1.首先是定义:
#define LH 1
#define EH 0
#define LH -1
#define TRUE 1
#define FALSE 0
第一个LH是左子树比右子树高1,EH是两棵子树高度相同,RH代表右子树比左子树高一个节点。
2.二叉树节点声明:
typedef struct BiTNode //二叉树生命
int data; //节点值
int bf; //平衡因子balance factor
struct BiTNode *left,*right; //声明左孩子跟右孩子
}BiTNode,*BiTree;
3.插入节点的操作:
BiTree InsertAVL(BiTNode *T, int e, int *taller)//二叉树插入操作
{
if(*T == NULL)//如果是一只空树
{
T = (*BiTree)malloc(sizeof(BiTree));//申请空间
T->data = e;
T->bf = EH;
T->left = T->right = NULL;
*taller = TRUE;//taller用来标识树是否增加高度
}
else
{
if(e == (*T)->data )//如果树中本来有这个数
{
T->bf = EH;
*taller = FALSE;
return FALSE;//返回插入失败
}
else if( e < (*T)->data )//如果小于节点值,则向左子树进行检查
{
if(!InsertAVL( &(*T)->lchild, e, taller))//检测是否插入失败
{
reutrn FALSE;
}
if(*taller)//如果树的高度加一,检测是否还是平衡,如果不平衡,就进行调整
{
switch((*T)->bf)//对节点T的平衡因子进行检测
{
case LH://左子树高
LeftBalance(T);//进行旋转调整
*taller = FASLE;//左子树高,原本应该变高,但旋转调整之后高度未增加
break;
case EH://两边一样高
*taller = TRUE;//高度加一个节点
(*T)->bf = LH;
break;
case RH://右子树高
(*T)->bf = EH;
*taller = FALSE;
break;
}
}
}
else//原理同上
{
if(!InsertAVL( &(*T)->rchild, e, taller))
{
reutrn FALSE;
}
if(*taller)
{
switch((*T)->data)
{
case LH:
(*T)->bf = EH;
*taller = FASLE;
break;
case EH:
*taller = TRUE;
(*T)->bf = RH;
break;
case RH:
RightBalance(T);
*taller = FALSE;
break;
}
}
}
}
}
4.左子树高,进行平衡操作:
void LeftBalance(BiTree *T) //左子数过长
{
BiTree L,Lr;
L = (*T)->left; //令L等于T的左孩子
switch(L->bf) //检查左孩子的平衡因子
{
case LH: //LL型
(*T)->bf = L->bf = EH;
R_Rotate(&(*T));
break;
case RH: //LR型
Lr = L->left; //检查T的左孩子的右孩子的平衡因子
switch(Lr->bf)
{
case LH: //如果平衡因子为1,而不是0或者-1,即左子树比右子树高一个节点
(*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); //后右旋
break;
}
}
5.右子树过高,进行平衡操作,原理同上:
void RightBalance(BiTree *T)//同上
{
BiTree R,Rl;
R = (*T)->right;
switch(R->bf)
{
case RH: //RR型
(*T)->bf = L->bf = EH;
L_Rotate(&(*T));
break;
case LH: //RL型
Rl = R->left;
switch(Rl->bf)
{
case LH:
(*T)->bf = EH;
L->bf = RH;
break;
case EH:
(*T)->bf = L->bf = EH;
break;
case RH:
(*T)->bf = LH;
L->right = EH;
break;
}
Rl->bf = EH;
R_Rotate(&(*T)->right);
L_Rotate(T);
break;
}
}
6.左旋操作:
void L_Rotate(BiTree *p) //左旋
{
BiTree R;
R = (*p)->right;
(*p)->right = R->left;
(*p)->right = (*p);
*p =R;
}
7.右旋操作:
void R_Rotate(BiTree *p) //右旋
{
BiTree L; //声明一个BiTree变量来储存p的左孩子
L = (*p)->left;
(*p)->left = L->right; //令p的左孩子L的右孩子等于p的左孩子
L->right = (*p); //将p作为其右孩子
*p = L; //将L放到根节点位置
}