平衡二叉树

277 阅读4分钟
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 100
typedef int Status;

//二叉树的二叉链表结点结构定义
typedef struct BiTNode{
    //结点数据
    int data;
    //结点平均因子
    int bf;
    //结点的左右孩子
    struct BiTNode *lchild,*rchild;
}BiTNode, *BiTree;

//右旋
//左子树比右子树高
void R_Rotate(BiTree *p){
    //拿到左子树
    BiTree L;
    L = (*p)->lchild;
    //p的左子树指向L的右子树
    (*p)->lchild = L->rchild;
    //L的右子树指向p
    L->rchild = *p;
    //将L设置为根结点
    *p = L;
}
//左旋
//右子树比左子树高
void L_Rotate(BiTree *p){
    //拿到右子树
    BiTree R;
    R = (*p)->rchild;
    //p的右子树指向R的左子树
    (*p)->rchild = R->lchild;
    //R的左子树指向p
    R->lchild = *p;
    //将R设置为根结点
    *p = R;
}

#define LH +1 /*  左高 */
#define EH 0  /*  等高 */
#define RH -1 /*  右高 */

//3.对指针T所指向的根的二叉树作平衡旋转处理,算法结束后,指针T指向平衡处理后新的根结点
void LeftBalance(BiTree *T){
    BiTree L,Lr;
    //1.指向T的左子树的根结点
    L = (*T)->lchild;
    //2.检查T的左子树的平衡度,并作相应平衡处理
    switch (L->bf) {
        case LH:
        {
            //2.1新结点插入在T的左孩子的左子树上,要作单右旋处理
            (*T)->bf = L->bf = EH;
            //右旋
            R_Rotate(T);
        }
            break;
        case RH:
        {
            //2.2L的平衡因子为RH(-1)时,它与根结点T的BF值符号相反,此时需要做双旋处理
            Lr = L->rchild;
            switch (Lr->bf) {
                case LH:
                {
                    (*T)->bf = RH;
                    L->bf =EH;
                    break;
                }
                    break;
                case EH:
                {
                    (*T)->bf = L->bf = EH;
                }
                    break;
                case RH:
                {
                    (*T)->bf = EH;
                    L->bf = LH;
                    
                }
                    break;
                default:
                    break;
            }
            Lr->bf = EH;
            //对T的左子树作左旋平衡处理
            L_Rotate(&(*T)->lchild);
            //对T作右旋处理
            R_Rotate(T);
        }
            break;
        default:
            break;
    }
}
//4.右子树失衡处理
void RightBalance(BiTree *T){
    BiTree R,Rl;
    //1.R指向T的右子树的根结点
    R = (*T)->rchild;
    //2.检查T的右子树的平衡度,并作相应处理
    switch (R->bf) {
        case RH:
        {
            //新结点插入在T的右孩子的右子树上,要作左旋处理
            (*T)->bf = R->bf = EH;
            L_Rotate(T);
        }
            break;
        case LH:
        {
            //新结点插入在T的右孩子的左子树上,要作双旋处理
            Rl = R->lchild;
            switch (Rl->bf) {
                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;
                default:
                    break;
            }
            Rl->bf = EH;
            //对T的右子树作右旋平衡处理
            R_Rotate(&(*T)->rchild);
            //对T作左旋平衡处理
            L_Rotate(T);
        }
            break;
        default:
            break;
    }
}

Status InsertAVL(BiTree *T,int e,Status *taller){
    if (!*T) {
        //1.插入新结点,树“长高”,置taller为TRUE
        //开辟一个新结点T
        *T=(BiTree)malloc(sizeof(BiTNode));
        //对新结点T的data赋值,并且让其左右孩子指向为空,T的bf值为EH
        (*T)->data=e;
        (*T)->lchild=(*T)->rchild=NULL;
        (*T)->bf=EH;
        //新结点默认"长高"
        *taller=TRUE;
    }else{
        if (e == (*T)->data) {
            //树中已存在和e有相同关键字的结点则不再插入
            *taller=FALSE;
            return FALSE;
        }else if (e <(*T)->data){
            //应继续在T的左子树中进行搜索
            if(!InsertAVL(&(*T)->lchild,e,taller))
            {
                //未插入
                return FALSE;
            }
            //已插入到T的左子树中且左子树“长高”
            if (*taller) {
//                检查T的平衡度
                switch((*T)->bf)
                {
                    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;
            }
           // 已插入到T的右子树且右子树“长高”
            if (*taller) {
                // 检查T的平衡度
                    switch((*T)->bf)
                {
                    //原本左子树比右子树高,现左、右子树等高
                    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;
}

/*6.二叉排序树查找*/
Status SearchBST(BiTree T,int key,BiTree f, BiTree *p){
    
    if (!T)    /*  查找不成功 */
    {
        *p = f;
        return FALSE;
    }
    else if (key==T->data) /*  查找成功 */
    {
        *p = T;
        return TRUE;
    }
    else if (key<T->data)
        return SearchBST(T->lchild, key, T, p);  /*  在左子树中继续查找 */
    else
        return SearchBST(T->rchild, key, T, p);  /*  在右子树中继续查找 */
}
int main(int argc, const char * argv[]) {
    printf("平衡二叉树 !\n");
    int i;
    int a[10]={3,2,1,4,5,6,7,10,9,8};
    //调整数组的顺序,最终生成的平衡二叉树高度是一样的.
    //int a[10]={8,9,1,4,5,6,7,10,2,3};
    //int a[10]={9,4,1,2,7,6,5,10,3,8};
    
    BiTree T=NULL;
    Status taller;
    int sum = 0;
    for(i=0;i<10;i++)
    {
        InsertAVL(&T,a[i],&taller);
        sum += taller;
        printf("插入%d,是否增加树的高度(%d)[YES->1 / NO->0]\n",a[i],taller);
    }
    
    printf("将数组a插入到平衡二叉树后,最终形成高度为%d的平衡二叉树\n",sum);
    
    BiTree p;
    int statusValue = SearchBST(T, 10, NULL, &p);
    printf("查找%d是否成功:%d (1->YES/0->NO)\n",p->data,statusValue);
    return 0;
}