平衡二叉樹(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 指向新的根結點*/
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM