8.2 平衡二叉树
平衡二叉树或者是一棵空的二叉排序树,或者是具有下列性质的二叉排序树:
(1) 根结点的左子树和右子树的深度最多相差1.
(2)根结点的左子树和右子树也都是平衡二叉树.
8.3 平衡二叉树的实现
BalanceBiTree.h
#ifndef BALANCEBITREE_H
#define BALANCEBITREE_H
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define LH 1
#define EH 0
#define RH -1
typedef int DataType;
typedef struct BiTNode
{
DataType data; //结点数据
int BF; //结点的平衡因子
struct BiTNode *lchild,*rchild; //左右孩子指针
}BiNode,*BiTree;
void CreateBalanceBiTree(BiTree *bt,DataType r[],int n);
void R_Rotate(BiTree *p); //以p为根结点的二叉排序树进行右旋转
void L_Rotate(BiTree *p); //以p为根结点的二叉排序树进行左旋转
void LeftBalance(BiTree *bt); //左子树调整
void RightBalance(BiTree *bt); //右子树调整
bool InsertAVL(BiTree *bt,DataType e,bool *taller); //插入
BiNode* SearchBST(BiTree *bt,DataType e);
void InOrder(BiTree *bt);
#endif
BalanceBiTree.c
#include "BalanceBiTree.h"
/*初始化平衡二叉树,并构建平衡二叉树*/
void CreateBalanceBiTree(BiTree *bt,DataType r[],int n)
{
(*bt) = (BiTree)malloc(sizeof(BiNode));
(*bt) = NULL;
int i;
bool taller;
for(i=0;i<n;i++)
{
InsertAVL(bt,r[i],&taller);
}
}
/*以p为根结点的二叉排序树进行右旋转*/
void R_Rotate(BiTree *p)
{
BiNode *L;
L = (*p)->lchild;
(*p)->lchild = L->rchild;
L->rchild = (*p);
(*p) = L;
}
/*以p为根结点的二叉排序树进行左旋转*/
void L_Rotate(BiTree *p)
{
BiNode *R;
R = (*p)->rchild;
(*p)->rchild = R->lchild;
R->lchild = (*p);
(*p) = R;
}
void LeftBalance(BiTree *bt)
{
BiNode *L,*Lr;
L = (*bt)->lchild;
switch(L->BF)
{
/*检查bt的左子树平衡度,并做相应的平衡处理*/
case LH: /*新结点插入在bt的左孩子的左子树上,做单右旋转处理*/
(*bt)->BF = L->BF = EH;
R_Rotate(bt);
break;
case RH: /*新结点插入在bt的左孩子的右子树上,做双旋转处理*/
Lr = L->rchild;
switch(Lr->BF)
{
case LH:
(*bt)->BF = RH;
L->BF = EH;
break;
case EH:
(*bt)->BF = L->BF = EH;
break;
case RH:
(*bt)->BF = EH;
L->BF = LH;
break;
}
Lr->BF = EH;
L_Rotate(&(*bt)->lchild);
R_Rotate(bt);
}
}
void RightBalance(BiTree *bt)
{
BiNode *R,*Rr;
R = (*bt)->rchild;
switch(R->BF)
{
/*检查bt的右子树平衡度,并做相应的平衡处理*/
case RH: /*新结点插入在bt的右孩子的右子树上,做单左旋转处理*/
(*bt)->BF = R->BF = EH;
L_Rotate(bt);
break;
case LH: /*新结点插入在bt的右孩子的左子树上,做双旋转处理*/
Rr = R->rchild;
switch(Rr->BF)
{
case LH:
(*bt)->BF = EH;
R->BF = RH;
break;
case EH:
(*bt)->BF = R->BF = EH;
break;
case RH:
(*bt)->BF = LH;
R->BF = EH;
break;
}
Rr->BF = EH;
R_Rotate(&(*bt)->rchild);
L_Rotate(bt);
}
}
/*若在平衡的二叉排序树bt中不存在和e有相同关键字的结点,则插入一个
* 数据元素e的新结点并返回1,否则返回0。若因插入而使二叉排序树
* 失去平衡,则作平衡旋转处理,taller反映bt长高与否。*/
bool InsertAVL(BiTree *bt,DataType e,bool *taller)
{
if((*bt) == NULL)
{
(*bt) = (BiTree)malloc(sizeof(BiNode));
(*bt)->data = e;
(*bt)->lchild = (*bt)->rchild = NULL;
(*bt)->BF = EH;
*taller = true;
}
else
{
if(e == (*bt)->data) //相等,不插入
{
*taller = false;
return false;
}
if(e<(*bt)->data)
{
if(InsertAVL(&(*bt)->lchild,e,taller)==false) //未插入
{
return false;
}
if(*taller == true)
{
switch((*bt)->BF)
{
case LH: //原本左子树比右子树高,需要做左平衡处理
LeftBalance(bt);
*taller = false;
break;
case EH: //原本左右子树等高,现因左子树增高而树增高
(*bt)->BF = LH;
*taller = true;
break;
case RH: //原本右子树比左子树高,现在左右子树等高
(*bt)->BF = EH;
*taller = false;
break;
}
}
}
else //在bt的右子树中搜寻
{
if(InsertAVL(&(*bt)->rchild,e,taller) == false)
{
return false;
}
if(*taller==true) //插入右子树,且右子树长高
{
switch((*bt)->BF)
{
case LH: //原本左子树比右子树高,现在左右子树等高
(*bt)->BF = EH;
*taller = false;
break;
case EH: //原本左右子树等高,现在右子树变高
(*bt)->BF = RH;
*taller = true;
break;
case RH: //原本右子树比左子树高,现在需做右平衡处理
RightBalance(bt);
*taller = false;
break;
}
}
}
}
return true;
}
BiNode* SearchBST(BiTree *bt,DataType e)
{
/*若*bt为空树,则查找失败*/
if(*bt == NULL)
{
return NULL;
}
/*否则,如果e等于(*bt)->data,则查找成功*/
else if((*bt)->data == e)
{
return *bt;
}
/*否则,如果e<(*bt)->data,则继续查找(*bt)的左子树*/
else if((*bt)->data > e){
return SearchBST(&(*bt)->lchild,e);
}
/*否则,如果e>(*bt)->data,则继续查找(*bt)的右子树*/
else{
return SearchBST(&(*bt)->rchild,e);
}
}
void InOrder(BiTree *bt)
{
if(*bt == NULL)
{
return ;
}
else{
InOrder(&(*bt)->lchild);
printf("%d\n",(*bt)->data);
InOrder(&(*bt)->rchild);
}
}
main.c
#include "BalanceBiTree.h"
int main(void)
{
int i;
int r[8] = {10,15,23,5,7,14,25,30};
BiTree B = NULL;
CreateBalanceBiTree(&B,r,8);
InOrder(&B);
printf("Search 7 :\n",SearchBST(&B,7));
return 0;
}