1、概念
平衡二叉树:是一种二叉排序树,其中每一个节点的左子树和有字数的高度差之多等于1。
平衡因子BF(Balance Factor):将二叉树上结点的左子树深度减去右子树深度的值。
最小不平衡子树:距离插入结点最近的,且平衡因子的绝对值大于1的结点为根的子树。
2、作用
我们知道,对于一般的二叉搜索树(Binary Search Tree),其期望高度(即为一棵平衡树时)为log2n,其各操作的时间复杂度(O(log2n))同时也由此而决定。但是,在某些极端的情况下(如在插入的序列是有序的时),二叉搜索树将退化成近似链或链,此时,其操作的时间复杂度将退化成线性的,即O(n)。我们可以通过随机化建立二叉搜索树来尽量的避免这种情况,但是在进行了多次的操作之后,由于在删除时,我们总是选择将待删除节点的后继代替它本身,这样就会造成总是右边的节点数目减少,以至于树向左偏沉。这同时也会造成树的平衡性受到破坏,提高它的操作的时间复杂度。
3、实现算法
/*二叉树的二叉链表结点结构定义*/ typedef struct BiTNode /*结点结构*/ { int data; /*结点数据*/ int bf; /*结点的平衡因子*/ struct BiTNode * lchild,*rchild; /*左右孩子指针*/ }BiTNode,*BiTree /*对以p为根的二叉排序树做右旋处理*/ /*处理后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为根的二叉排序树做左旋处理*/ /*处理之后p指向新的根结点,即旋转处理之前的右子树的根结点0*/ void L_Rotate(BiTree *p) { BiTree R; R=(*p)->rchild; /*R指向p的右子树根结点*/ (*p)->rchild=R->lchild; /*R的右子树挂接为p的右子树*/ R->lchild=(*p); *p=R; /*p指向新的根结点*/ } #define LH +1 /*左高*/ #define EH 0 /*等高*/ #define RH -1 /*右高*/ /*对以指针T所指结点为根的二叉树做左平衡旋转处理*/ /*本算法结束时,指针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; /*Lr指向T的左孩子的右子树根*/ switch(Lr->br) /*修改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); /*对T的左子树做左旋平衡处理*/ R_Rotate(T); /*对T做右旋平衡处理*/ } } #define LH +1 /*左高*/ #define EH 0 /*等高*/ #define RH -1 /*右高*/ /*对以指针T所指结点为根的二叉树做右平衡旋转处理*/ /*本算法结束时,指针T指向新的根结点*/ void RightBalance(BiTree *T) { BiTree L,Ll; L=(*T)->rchild; /*L指向T的右子树根结点*/ switch(L->bf) { /*检查T的右子树的平衡度,并作相应平衡处理*/ case RH: /*新结点插入在T的右孩子的右子树上,要做单左旋处理*/ (*T)->bf=L->bf=EH; L_Rotate(T); break; case LH: /*新结点插入在T的右孩子的左子树上,要做双旋转处理*/ Ll=L->lchild; /*Ll指向T的右孩子的左子树根*/ switch(Ll->br) /*修改T及其右孩子的平衡因子*/ { case LH: (*T)->bf=EH; L->bf=RH; break; case EH: (*T)->bf=L->bf=EH; break; case RH: (*T)->bf=LH; L->bf=EH; break; } Ll->bf=EH; R_Rotate(&(*T)->rchild); /*对T的右子树做右旋平衡处理*/ L_Rotate(T); /*对T做左旋平衡处理*/ } } /*若在平衡的二叉排序树T中不存在和e有相同关键字的结点,则插入一个*/ /*数据元素为e的新结点并返回1,否则返回0.若因插入而使二叉排序树失去平衡,则做平衡旋转处理*/ /*布尔变量taller反应T长高与否*/ Status InsertAVL(BiTree *T,int e,Status *taller) { if(!*T) /*如果不存在T*/ { /*插入新结点,树“长高”,置taller为TRUE*/ *T=(BiTree)malloc(sizeof(BiTNode)); (*T)->data=e; (*T)->lchild=(*T)->rchild=NULL; (*T)->bf=EH; *taller=TRUE; } else { if(e==(*T)->data) { /*树中已存在和e有相同关键字的结点则不再插入*/ *taller=FALSE; return FALSE; } 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 FALSE; 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 TRUE; }