C语言实现平衡二叉树

来源:互联网 发布:深圳市超惠转网络推广 编辑:程序博客网 时间:2024/06/06 02:00

平衡二叉树(Self-Balancing Binary Search Tree),是一种二叉排序树,其中每个结点的左子树和右子树的高度差为-1,0,1之中的某个值。

二叉平衡树又称为AVL树。

平衡因子BF是指二叉树上结点的左子树深度减去右子树深度的值。

只要二叉树上有一个结点的平衡因子的绝对值大于1,则该二叉树就是不平衡的。

平衡二叉树构建的基本思想是在构建二叉排序树的过程中,每当插入一个结点时,先检查是否因插入二破坏了树的平衡性,若是,则找出最小不平衡子树。在保持二叉树特性的前提下,调整最小不平衡子树之间的链接关系,进行相应的旋转,使之称为新的平衡子树。

当最小不平衡子树根结点的BF大于1时,右旋,小于-1时,左旋。插入结点后,最小不平衡子树的BF与它的子树的BF符号相反时,就需要先对结点进行一次旋转以是的符号相同后,再反向旋转一次才能够完成平衡操作。

以下程序在DEV C++中调试运行通过。

#include<stdio.h>#include<stdlib.h>#define LH 1#define EH 0#define RH -1typedef struct BiTNode{int data;int bf;struct BiTNode *lchild,*rchild;}BiTNode,*BiTree;//对以P为根的二叉排序树作右旋处理 void R_Rotate(BiTree *P){BiTree L;L=(*P)->lchild;//L指向P的左子树根结点 (*P)->lchild=L->rchild;//L的右子树挂接为P的左子树 L->rchild=(*P);*P=L;//P指向新的根结点 }//对以P为根的二叉排序树作左旋处理 void L_Rotate(BiTree *P){BiTree R;R=(*P)->rchild;//R指向P的右子树根结点 (*P)->rchild=R->lchild;//R的左子树挂接为P的右子树 R->lchild=(*P);*P=R;//P指向新的根结点 }//对以T为根节点的二叉树作左平衡旋转处理void LeftBalance(BiTree *T){BiTree L,Lr;L=(*T)->lchild;//L指向T的左子树根结点switch(L->bf){//检查T的左子树平衡度,并作相应平衡处理case LH://新结点插入在T的左孩子的左子树上,要作单右旋处理(*T)->bf=L->bf=EH;R_Rotate(T);break;case RH://新结点插入在T的左孩子的右子树上,要作双旋处理Lr=L->rchild;switch(Lr->bf)//修改T及其左孩子的平衡因子{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); }  } //对以T为根节点的二叉树作右平衡旋转处理void RightBalance(BiTree *T){BiTree R,Rl;R=(*T)->rchild;switch(R->bf){//检查T的右子树平衡度,并作相应平衡处理case RH://新结点插入在T的左孩子的左子树上,要作单右旋处理(*T)->bf=R->bf=EH;L_Rotate(T);break;case LH://新结点插入在T的左孩子的右子树上,要作双旋处理Rl=R->lchild;switch(Rl->bf)//修改T及其左孩子的平衡因子{case RH:(*T)->bf=LH;R->bf=EH;break;case EH:(*T)->bf=R->bf=EH;break;case LH:(*T)->bf=EH;R->bf=RH;break; }  Rl->bf=EH; R_Rotate(&(*T)->rchild); L_Rotate(T); }  } //若在平衡的二叉排序树T中不存在和e有相同关键字的结点,则插入一个数据元素为e的新结点并返回1,否则返回0//若因插入而使二叉排序树失去平衡,则做平衡旋转处理,变量taller反应T长高与否int InsertAVL(BiTree *T,int e,int *taller){if(!*T){//插入新结点,树长高,置taller为1*T=(BiTree)malloc(sizeof(BiTNode));(*T)->data=e;(*T)->lchild=(*T)->rchild=NULL;(*T)->bf=EH;*taller=1;}else{if(e==(*T)->data){//树中已存在和e相同关键字的结点则不再插入*taller=0;return 0; }if(e<(*T)->data){//应继续在T的左子树中进行搜索if(!InsertAVL(&(*T)->lchild,e,taller))//未插入return 0;if(*taller)//已插入到T的左子树中且左子树“长高”{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{//应继续在T的右子树中进行搜索if(!InsertAVL(&(*T)->rchild,e,taller))return 0;if(*taller)//已插入到T的右子树中且右子树“长高”{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; } int main(){int i,j;int a[10]={3,2,1,4,5,6,7,10,9,8};BiTree T=NULL;int taller;for(i=0;i<10;i++){j=InsertAVL(&T,a[i],&taller);if(j==1)printf("第%d个数插入成功\n",i+1);}}

运行结果如图所示。


原创粉丝点击