/************************************************************************/
/* C实现平衡二叉树---AVL */
/************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#define LH (+1) /*左高*/
#define EH 0 /*等高*/
#define RH (-1) /*右高*/
#define TRUE 1
#define FALSE 0
typedef int ElemType;
typedef struct BiTNode /*结点结构*/
{
ElemType data; /*结点数据*/
int bf; /*平衡因子*/
struct BiTNode *lchild,*rchild; /*左右孩子指针*/
}BiTNode,*BiTree;
/***********************************************************************
对以p为根的二叉树作右旋操作,处理之后
p指向新的根结点,即旋转处理之前的左子树的根结点
************************************************************************/
void R_Rotate(BiTree* p)
{
BiTree lc = (*p)->lchild;
(*p)->lchild = lc->rchild;
lc->rchild = *p;
*p = lc;
}
/***********************************************************************
对以p为根的二叉树作左旋操作,处理之后
p指向新的根结点,即旋转处理之前的左子树的根结点
************************************************************************/
void L_Rotate(BiTree* p)
{
BiTree rc = (*p)->rchild;
(*p)->rchild = rc->lchild;
rc->lchild = *p;
*p = rc;
}
/***********************************************************************
对以指针T所指结点为根的二叉树作左平衡旋转处理
本算法结束时,指针T指向新的根结点
************************************************************************/
void LeftBalance(BiTree* T)
{
BiTree lc,rd;
lc = (*T)->lchild; /*lc指向T的左子树根结点*/
switch (lc->bf)
{
/*检查T的左子树的平衡度,并作相应平衡处理*/
case LH: /*新插入的结点在T的左孩子的左子树上,要作单右旋处理*/
{
(*T)->bf = lc->bf = EH;
R_Rotate(T);
break;
}
case RH: /*新插入的结点在T的左孩子的右子树上,要作双旋处理*/
{
rd = lc->rchild; /*rd指向T的左孩子的右子树的根*/
switch(rd->bf) /*修改T极其左孩子的平衡因子*/
{
case LH:
{
(*T)->bf = RH;
lc->bf = EH;
break;
}
case EH:
{
(*T)->bf = lc->bf = EH;
break;
}
case RH:
{
(*T)->bf = EH;
lc->bf = LH;
break;
}
}
}
rd->bf = EH;
L_Rotate(&(*T)->lchild); /*对T的左子树作左旋平衡处理*/
R_Rotate(T); /*对T作右旋平衡处理*/
break;
}
}
/***********************************************************************
对以指针T所指结点为根的二叉树作右平衡旋转处理
本算法结束时,指针T指向新的根结点
************************************************************************/
void RightBalance(BiTree* T)
{
BiTree lc,rd;
lc= (*T)->rchild; /*lc指向T的右子树根结点*/
switch (lc->bf)
{
/*检查T的右子树的平衡度,并作相应平衡处理*/
case RH: /*新插入的结点在T的右孩子的右子树上,要作单左旋处理*/
{
(*T)->bf = lc->bf = EH;
L_Rotate(T);
break;
}
case LH: /*新插入的结点在T的右孩子的左子树上,要作双旋处理*/
{
rd = lc->lchild; /*rd指向T的右孩子的左子树的根*/
switch(rd->bf) /*修改T极其右孩子的平衡因子*/
{
case LH:
{
(*T)->bf = EH;
lc->bf = RH;
break;
}
case EH:
{
(*T)->bf = lc->bf = EH;
break;
}
case RH:
{
(*T)->bf = EH;
lc->bf = LH;
break;
}
}
}
rd->bf = EH;
R_Rotate(&(*T)->rchild); /*对T的右子树作右旋平衡处理*/
L_Rotate(T); /*对T作左旋平衡处理*/
break;
}
}
/***********************************************************************
若在平衡的二叉排序树T中不存在和e有相同关键字的结点,
则插入一个数据元素为e的新结点并返回1,否则返回0 。
若因插入而使二叉排序树失去平衡,则作平衡旋转处理,
变量taller反映T长高与否。
************************************************************************/
int InsertAVL(BiTree* T,ElemType e,int* taller)
{
if ((*T)==NULL)
{ /*插入新结点,树长高,置taller为TRUE*/
*T=(BiTree)malloc(sizeof(BiTNode));
(*T)->bf = EH;
(*T)->data = e;
(*T)->lchild = NULL;
(*T)->rchild = NULL;
*taller = TRUE;
}
else if (e == (*T)->data)
{ /*树中已存在和e有相同关键字的结点则不再插入*/
*taller = FALSE;
return FALSE;
}
else if (e < (*T)->data)
{ /*应继续在T的左子树中进行搜索*/
if(!InsertAVL(&(*T)->lchild,e,taller)) /*未插入*/
{
return FALSE;
}
if(*taller) /*已插入到T的左子树中且左子树长高*/
{
switch ((*T)->bf) /*检查T的平衡度*/
{
case LH: /*原本左子树比右子树高,需要作左平衡处理*/
{
LeftBalance(T);
*taller = FALSE;
break;
}
case EH: /*原本左右子树等高,现因左子树长高而树长高*/
{
(*T)->bf = LH;
*taller = TRUE;
break;
}
case RH: /*原本右子树比左子树高,现左右子树等高*/
{
(*T)->bf = EH;
*taller = FALSE;
break;
}
}
}
}
else
{ /*应继续在T的右子树中进行搜索*/
if(!InsertAVL(&(*T)->rchild,e,taller)) /*未插入*/
{
return 0;
}
if (*taller) /*已插入到T的右子树中且右子树长高*/
{
switch ((*T)->bf) /*检查T的平衡度*/
{
case LH: /*原本左子树比右子树高,现左右子树等高*/
{
(*T)->bf = EH;
*taller = FALSE;
break;
}
case EH: /*原本左右子树等高,现因右子树长高而树长高*/
{
(*T)->bf = RH;
*taller = TRUE;
break;
}
case RH: /*原本右子树比左子树高,需要作右平衡处理*/
{
RightBalance(T);
*taller = FALSE;
break;
}
}
}
}
return 1;
}
/***********************************************************************
在平衡二叉树root中查找元素e,若存在则pos指向该节点
并返回TRUE,否则返回FALSE。
************************************************************************/
int FindNode(BiTree root,ElemType e,BiTree* pos)
{
BiTree pt = root;
(*pos) = NULL;
while(pt)
{
if (pt->data == e) /*找到节点,pos指向该节点并返回true */
{
(*pos) = pt;
return TRUE;
}
else
{
if (pt->data > e)
{
pt = pt->lchild;
}
else
{
pt = pt->rchild;
}
}
}
return FALSE;
}
/***********************************************************************
在平衡二叉树中搜索关键字
************************************************************************/
void Find(BiTree root)
{
BiTree pos=NULL;
int num;
printf("Input the num to find:\n");
scanf(" %d",&num);
if(FindNode(root,num,&pos))
{
printf("\n%d is found\n",pos->data);
}
else
{
printf("\nNot find this Node\n");
}
}
/***********************************************************************
中根遍历平衡二叉树root,并输出结点
************************************************************************/
void InorderTra(BiTree root)
{
if(root->lchild)
{
InorderTra(root->lchild);
}
printf("%d ",root->data);
if(root->rchild)
{
InorderTra(root->rchild);
}
}
/***********************************************************************
先根遍历平衡二叉树root,并输出结点(带空结点)
************************************************************************/
void PreorderTra(BiTree root)
{
if(root == NULL)
{
printf("^ ");
return ;
}
else
{
printf("%d ",root->data);
PreorderTra(root->lchild);
PreorderTra(root->rchild);
}
}
/***********************************************************************
在删除结点时进行左平衡处理
************************************************************************/
void LeftProcess1(BiTree *p,int *taller)
{
BiTree p1,p2;
if ((*p)->bf==1)
{
(*p)->bf=0;
*taller=1;
}
else
{
if ((*p)->bf==0)
{
(*p)->bf=-1;
*taller=0;
}
else /*p->bf=-1*/
{
p1=(*p)->rchild;
if (p1->bf==0) /*需作RR调整*/
{
(*p)->rchild=p1->lchild;
p1->lchild=(*p);
p1->bf=1;
(*p)->bf=-1;
(*p)=p1;
*taller=0;
}
else
{
if (p1->bf==-1) /*需作RR调整*/
{
(*p)->rchild=p1->lchild;
p1->lchild=(*p);
(*p)->bf=p1->bf=0;
(*p)=p1;
*taller=1;
}
else /*需作RL调整*/
{
p2=p1->lchild;
p1->lchild=p2->rchild;
p2->rchild=p1;
(*p)->rchild=p2->lchild;
p2->lchild=(*p);
if (p2->bf==0)
{
(*p)->bf=0;
p1->bf=0;
}
else
{
if (p2->bf==-1)
{
(*p)->bf=1;
p1->bf=0;
}
else
{
(*p)->bf=0;
p1->bf=-1;
}
}
p2->bf=0;
(*p)=p2;
*taller=1;
}
}
}
}
}
/***********************************************************************
在删除结点时进行右平衡处理
************************************************************************/
void RightProcess1(BiTree *p,int *taller)
{
BiTree p1,p2;
if ((*p)->bf==-1)
{
(*p)->bf=0;
*taller=-1;
}
else
{
if ((*p)->bf==0)
{
(*p)->bf=1;
*taller=0;
}
else /*(*p)->bf=1*/
{
p1=(*p)->lchild;
if (p1->bf==0) /*需作LL调整*/
{
(*p)->lchild=p1->rchild;
p1->rchild=(*p);
p1->bf=-1;
(*p)->bf=1;
(*p)=p1;
*taller=0;
}
else
{
if (p1->bf==1) /*需作LL调整*/
{
(*p)->lchild=p1->rchild;
p1->rchild=(*p);
(*p)->bf=p1->bf=0;
(*p)=p1;
*taller=1;
}
else /*需作LR调整*/
{
p2=p1->rchild;
p1->rchild=p2->lchild;
p2->lchild=p1;
(*p)->lchild=p2->rchild;
p2->rchild=(*p);
if (p2->bf==0)
{
(*p)->bf=0;
p1->bf=0;
}
else
{
if (p2->bf==1)
{
(*p)->bf=-1;
p1->bf=0;
}
else
{
(*p)->bf=0;
p1->bf=1;
}
}
p2->bf=0;
(*p)=p2;
*taller=1;
}
}
}
}
}
/****************************************************************************
由DeleteAVL()调用,用于处理被删结点左右子树均不空的情况
*****************************************************************************/
void Delete2(BiTree q,BiTree *r,int *taller)
{
if ((*r)->rchild==NULL)
{
q->data=(*r)->data;
q=*r;
(*r)=(*r)->lchild;
free(q);
*taller=1;
}
else
{
Delete2(q,&((*r)->rchild),taller);
if (*taller==1)
{
RightProcess1(r,taller);
}
}
}
/****************************************************************************
在AVL树p中删除关键字为x的结点
*****************************************************************************/
int DeleteAVL(BiTree *p,ElemType x,int *taller)
{
int k;
BiTree q;
if ((*p)==NULL)
{
return 0;
}
if (x < (*p)->data)
{
k=DeleteAVL(&((*p)->lchild),x,taller);
if (*taller==1)
{
LeftProcess1(p,taller);
}
return k;
}
else
{
if (x > (*p)->data)
{
k=DeleteAVL(&((*p)->rchild),x,taller);
if (*taller==1)
{
RightProcess1(p,taller);
}
return k;
}
else /*找到了关键字为x的结点,由p指向它*/
{
q=(*p);
if ((*p)->rchild==NULL) /*被删结点右子树为空*/
{
(*p)=(*p)->lchild;
free(q);
*taller=1;
}
else
{
if ((*p)->lchild==NULL) /*被删结点左子树为空*/
{
(*p)=(*p)->rchild;
free(q);
*taller=1;
}
else /*被删结点左右子树均不空*/
{
Delete2(q,&(q->lchild),taller);
if (*taller==1)
{
LeftProcess1(&q,taller);
}
(*p)=q;
}
}
return 1;
}
}
}
int main()
{
int i;
int nArr[] = {1,23,45,43,38,95,23,42,55};
BiTree root=NULL;//,pos=NULL;
int taller;
for (i=0;i<9;i++)
{
InsertAVL(&root,nArr[i],&taller);
}
while(1)
{
printf("1.InorderTra\n");
printf("2.PreorderTra\n");
printf("3.Insert\n");
printf("4.Delete:\n");
printf("5.Find:\n");
scanf(" %d",&i);
switch(i)
{
case 1:
{
printf("InorderTra:\n");
InorderTra(root);
printf("\n");
break;
}
case 2:
{
printf("PreorderTra:\n");
PreorderTra(root);
printf("\n");
break;
}
case 3:
{
printf("Insert:\n");
scanf(" %d",&i);
InsertAVL(&root,i,&taller);
break;
}
case 4:
{
printf("Delete:\n");
scanf(" %d",&i);
DeleteAVL(&root,i,&taller);
break;
}
case 5:
{
Find(root);
break;
}
default:
{
break;
}
}
}
return 0;
}
【修改】C实现平衡二叉树---AVL
最新推荐文章于 2024-04-06 15:06:05 发布
本文介绍了一种使用C语言实现的AVL平衡二叉树,包括插入、查找、中序遍历、先序遍历、删除、平衡旋转等关键操作。详细解释了如何在插入元素时维护树的平衡,以及删除节点后的平衡处理方法。
7734

被折叠的 条评论
为什么被折叠?



