16 - 12 - 12 平衡二叉树 (AVL树) --代码详解

关于旋转的原理,在http://blog.csdn.net/sodaoo/article/details/53572100 有着精妙的阐释~~
平衡因子为正:右旋
平衡因子为正:左旋
简记:右边为正左为负。

关键:把不平衡消灭在最初时刻:
那么我们先来看插入代码,在一个一个插入的过程中,消灭不平衡就是我们的理念啦~

int InsertAVL(BiTree *T,int e,int *taller)
{
    if(!T)
    {  /*插入新节点使树长高,至taller为TRUE,是不是看不懂 (!T)?,先到下面看看 第4个if()语句(递归的) 就可以了。因为当执行到这一步代码时,说明成功插入一个节点*/
        (*T) = (BiTree)malloc(sizeof(BiTNode));
        (*T)->data = e;
        (*T)->lchild = (*T)->rchild = NULL;
        (*T)->bf = EH;  //0
        *taller = TRUE;
    }else{
        if(e==(*T)->data) { //若树中已存在 相同关键字的节点 则不再插入 *taller = FALSE; return FALSE; } if(e<(*T)->data){ /*继续在 T 的左子树中进行搜索,直至T = NULL*/ if(!InsertAVL(&(*T)->lchild,e,taller)) //未插入 return FALSE; if(taller) /*已经插入到T的左子树中且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(!InsertBST(&(*T)->rchild,e,taller) /*未插入*/ return FALSE; if(*taller) /*已插入到T的右子树且右子树长高*/ { switch((*T)->bf) /*检查p的平衡度*/ { 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; } 

*
*
*

//单右旋操作(调整LL树)(看 图一!!!!)

/*对以 p 为根的二叉排序树做右旋处理,处理之后p指向新的树根结点, 即:旋转处理之前的左子树的根节点*/
void R_Rotate(BiTree *p)
{
    BiTree L;
    L = (*p)->lchild;
    (*p)->lchild = L->rchild;
    L->rchild = (*p);
    *p = L;
}    //(图一 ↓ )

《16 - 12 - 12 平衡二叉树 (AVL树) --代码详解》
*
*
*
*

//单左旋操作(调整RR树,图二)

void  L_Rotate(BiTree *p)
{
    BiTree R;
    R = (*p)->rchild;
    (*p)->rchild = R->lchild;
    R->lchild = (*p);
    *p = R;          
}

《16 - 12 - 12 平衡二叉树 (AVL树) --代码详解》
*
*
*
*
*

/*左平衡旋转处理(包括LL/LR)

个人见解:当各节点的平衡因子出现异号时,做左平衡旋转处理*/
#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)
    {
        case LH:   /*新节点插入在T的左孩子的左子树上(RR),要做"单右旋"处理*/
            (*T)->bf = L->bf = EH;
            R_Rotate(T);  break;
        case RH:   /*新节点插入在T的左孩子的右子树上,要做"双旋"处理*/
            Lr = L->rchild;   /*Lr指向T的左孩子的右子树根*/
            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); /*对T的左子树做"单左旋"平衡处理*/ R_Rotate(T); /*对T做"单右旋"平衡处理*/ } } //图三 ↓

《16 - 12 - 12 平衡二叉树 (AVL树) --代码详解》

*
*
*
*
*

↓ <<<<<完整代码~~>>>>> ↓

<<<<<完整代码~~>>>>>
/*~平衡二叉树~*/
typedef struct BiTNode
{
    int data;
    int bf;   //节点的平衡因子。
    struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;

//单右旋操作(调整LL树)(看 图一!!!!):
/*对以 p 为根的二叉排序树做右旋处理,处理之后p指向新的树根结点,
即:旋转处理之前的左子树的根节点*/
void R_Rotate(BiTree *p)
{
    BiTree L;
    L = (*p)->lchild;
    (*p)->lchild = L->rchild;
    L->rchild = (*p);
    *p = L;
}    //(图一 ↓ )
//单左旋操作(调整RR树,图二)
void  L_Rotate(BiTree *p)
{
    BiTree R;
    R = (*p)->rchild;
    (*p)->rchild = R->lchild;
    R->lchild = (*p);
    *p = R;          
}

/*左平衡旋转处理(包括LL/LR),个人见解:当各节点的平衡因子出现异号时,做左平衡旋转处理*/
#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)
    {
        case LH:   /*新节点插入在T的左孩子的左子树上(RR),要做"单右旋"处理*/
            (*T)->bf = L->bf = EH;
            R_Rotate(T);  break;
        case RH:   /*新节点插入在T的左孩子的右子树上,要做"双旋"处理*/
            Lr = L->rchild;   /*Lr指向T的左孩子的右子树根*/
            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); /*对T的左子树做"单左旋"平衡处理*/ R_Rotate(T); /*对T做"单右旋"平衡处理*/ } } /*若在 平衡的二叉排序树中不存在和e有相同关键字的节点,则插入一个 数据元素e,并返回1,否则0。若是 因为插入而使二叉排序树失去平衡 则作平衡旋转旋转处理,布尔变量taller反映T树长高了没有*/ int InsertAVL(BiTree *T,int e,int *taller) { if(!T) { /*插入新节点使树长高,至tallerTRUE,是不是看不懂 (!T)?,先到下面看看 第4个if()语句(递归的) 就可以了。因为当执行到这一步代码时,说明成功插入一个节点*/ (*T) = (BiTree)malloc(sizeof(BiTNode)); (*T)->data = e;
        (*T)->lchild = (*T)->rchild = NULL;
        (*T)->bf = EH;  //0
        *taller = TRUE;
    }else{
        if(e==(*T)->data) { //若树中已存在 相同关键字的节点 则不再插入 *taller = FALSE; return FALSE; } if(e<(*T)->data){ /*继续在 T 的左子树中进行搜索,直至T = NULL*/ if(!InsertAVL(&(*T)->lchild,e,taller)) //未插入 return FALSE; if(taller) /*已经插入到T的左子树中且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(!InsertBST(&(*T)->rchild,e,taller) /*未插入*/ return FALSE; if(*taller) /*已插入到T的右子树且右子树长高*/ { switch((*T)->bf) /*检查p的平衡度*/ { 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; } 
    原文作者:AVL树
    原文地址: https://blog.csdn.net/SoDaoo/article/details/53581952
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞