平衡二叉树(C语言)

 

我觉得这个是最通俗易懂的版本了,,改编自网上,,出处忘了,我完整了他的代码,并把风格改成我的了,,函数实在不喜欢一股脑的全部扔上面,。,,,。

 

建议阅读这两篇文章:

 

http://www.cnki.net/KCMS/detail/detail.aspx?QueryID=2&CurRec=1&recid=&filename=GWDT201034126&dbname=CJFDN0911&dbcode=CJFR&pr=CJFR2010;CFJD2010;&urlid=&yx=&uid=WEEvREcwSlJHSldRa1FiNlpyakNuRFRyd0tkTUkwazlLWW5tbjYzYXFVV3pDK3pWYjBQN3ZZNjdKQTlVQkpWN3l3PT0=$9A4hF_YAuvQ5obgVAqNKPCYcEjKensW4IQMovwHtwkF4VYPoHbKxJw!!&v=MDAyOTJGeURsVzd2SUlqclBlckc0SDlIUHE0NUhZb1I4ZVgxTHV4WVM3RGgxVDNxVHJXTTFGckNVUkw2ZVplZHE=

http://www.cnblogs.com/fornever/archive/2011/11/15/2249492.html

 

 

#include<stdio.h>
#include<stdlib.h>
#define EH 0            /*等高*/
#define LH 1            /*左高*/
#define RH -1            /*右高*/
    
typedef int ElemType;                 /*数据类型*/

typedef struct BiTree{
    ElemType data;                    /*数据元素*/
    int BF;                         /*平衡因子*/
    struct BiTree *lchild,*rchild;     /*左右子女指针*/
}*Bitree,BitreeNode;


int InsertAVL(Bitree *T,ElemType e,bool *taller);
void LeftBalance(Bitree *T);
void RightBalance(Bitree *T);
void R_Rotate(Bitree *T);
void L_Rotate(Bitree *T);
bool *taller=(bool*)malloc(sizeof(bool));

int main(void)
{
    int data;
    Bitree T=NULL;
    while(1)
    {
        printf("enter the number(zero to exit):");
        scanf("%d",&data);
        if(0==data)break;
        InsertAVL(&T,data,taller);
        
    }
    
    
    
    return 0;
}


/*若在平衡的二叉排序树T 中不存在和e 有相同关键码的结点,则插入一个数据元素为e 的*/
/*新结点,并反回1,否则反回0。若因插入而使二叉排序树失去平衡,则作平衡旋转处理,*/        
/*布尔型变量taller 反映T 长高与否*/    
int InsertAVL(Bitree *T,ElemType e,bool *taller)
{
    if(!*T)                /*插入新结点,树“长高”,置taller 为TURE*/
    {
        (*T)=(Bitree)malloc(sizeof(BitreeNode));
        (*T)->data = e;
        (*T)->lchild = (*T)->rchild = NULL;
        (*T)->BF = EH;
        *taller = true;
    }
    else
    {
        if(e==(*T)->data)        /*树中存在和e 有相同关键码的结点,不插入*/
        {
            *taller = false;
            return 0;
        }    
        if(e<(*T)->data)
        {
            if(!InsertAVL(&(*T)->lchild,e,taller))    return 0;  /*未插入*/
            if(*taller)
            switch((*T)->BF)
            {    
                case EH :                    /*原本左、右子树等高,因左子树增高使树增高*/
                    (*T)->BF=LH;
                    *taller=true;
                    break;
                
                case LH :                    /*原本左子树高,需作左平衡处理*/
                    LeftBalance(T);
                    *taller=false;
                    break;
                
                case RH :                    /*原本右子树高,使左、右子树等高*/
                    (*T)->BF=EH; 
                    *taller=false;
                    break;
                    
            }
            
        }
        else
        {
            if(!InsertAVL(&(*T)->rchild,e,taller))    return 0;  /*未插入*/
            if(*taller)
            switch((*T)->BF)
            {    
                case EH :                    /*原本左、右子树等高,因右子树增高使树增高*/
                    (*T)->BF=RH;
                    *taller=true;
                    break;
                
                case LH :                    /*原本左子树高,使左、右子树等高*/
                    (*T)->BF=EH; 
                     *taller=false;
                     break;
                
                case RH :                    /*原本右子树高,需作右平衡处理*/
                    RightBalance(T);
                    *taller=false;
                     break;
                    
            }
        }
    }
    return 1;
}



/*对以*p 指向的结点为根的子树,作左平衡旋转处理,处理之后,*p 指向的结点为子树的新根*/
void LeftBalance(Bitree *T)
{
    Bitree L=(*T)->lchild,Lr;             /*L 指向*T左子树根结点*/
    switch(L->BF)                /*检查L 平衡度,并作相应处理*/
    {
        case LH:                    /*新结点插在*p 左子树的左子树上,需作单右旋转处理*/
            (*T)->BF=L->BF=EH;
             R_Rotate(T);
             break;
        case EH:             /*原本左、右子树等高,因左子树增高使树增高*/
            (*T)->BF=LH;    //这里的EH好像没有写的必要 
              *taller=true;
              break;
        case RH:                     /*新结点插在*T 左孩子的右子树上,需作先左后右双旋处理*/
            Lr=L->rchild;             /*Lr 指向*p 左孩子的右子树根结点*/    
            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(&L);        /*对*T 的左子树作左旋转处理*/
            R_Rotate(T);        /*对*T 作右旋转处理*/
    }
}
//这里和leftbalance一个道理,试着自己写一下 
void RightBalance(Bitree *T)
{
    Bitree Lr= (*T)->rchild,L;
    switch(Lr->BF)
    {
        case EH:
            *taller = true;
            (*T)->BF = RH;
            break;
        case RH:
            (*T)->BF=Lr->BF=EH;
            L_Rotate(T);
            break;
        case LH:
            L = Lr->lchild;
            switch(L->BF)
            {
                case EH:
                    (*T)->BF=Lr->BF= EH;
                    break;
                case RH:
                    Lr->BF= EH;
                    (*T)->BF = LH;
                    break;
                case LH:
                    (*T)->BF = LH;
                    Lr->BF = EH;
                    break;
                
            }
            L->BF = EH;
            R_Rotate(&Lr);        
            L_Rotate(T);    
        
    }
}


/*对以*T 指向的结点为根的子树,作右单旋转处理,处理之后,*T 指向的结点为子树的新根*/
void R_Rotate(Bitree *T)
{ 
    Bitree L=(*T)->lchild;                 /*L 指向*T 左子树根结点*/
    (*T)->lchild=L->rchild;                 /*L 的右子树挂接*T 的左子树*/
    L->rchild=*T; *T=L;             /* *L 指向新的根结点*/
}


/*对以*p 指向的结点为根的子树,作左单旋转处理,处理之后,*p 指向的结点为子树的新根*/
void L_Rotate(Bitree *T)
{ 
    Bitree Lr=(*T)->rchild;                 /*Lr 指向*T 右子树根结点*/
    (*T)->rchild=Lr->lchild;                 /*L 的左子树挂接*p 的右子树*/
    Lr->lchild=*T; 
    *T=Lr;                                     /* *L 指向新的根结点*/
}

 

posted @ 2015-04-27 11:40  _如此甚好  阅读(3791)  评论(1编辑  收藏  举报