平衡二叉树AVL

右旋操作

//对以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指向新的树根结点,即旋转处理之前的右子树的根节点
*/
void L_Rotate(BiTree &p){
    BiTree R;
    R=p->rchild;//R指向P的右子树的根节点
    p->rchild=R->lchild;//R的左子树挂接为p的右子树
    R->lchild=p;
    p=R;//p指向新的根节点
}

左平衡旋转处理

/*对以指针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->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作右旋平衡处理

    }
}

右平衡旋转处理

void RightBalance(BiTree &T){
    BiTree R,Rl;
    R=T->rchild;
    switch(R->bf){
        case RH://对应于RR
            T->bf=R->bf=EH;
            L_Rotate(T);
            break;
        case LH://对应于RL
            Rl=R->lchild;
            switch(Rl->bf){
                case LH:
                    T->bf=EH;
                    R->bf=RH;
                    break;
                case EH:
                    T->bf=R->bf=EH;
                    break;
                case RH:
                    T->bf=LH;
                    R->bf=EH;
                    break;
            }
            Rl->bf=EH;
            R_Rotate(T->rchild);
            L_Rotate(T);
    }
}

平衡二叉树的插入

/*
若在平衡的二叉排序树T中不存在和e有相同关键字的结点,则插入一个
数据元素为e的新结点,并返回true;否则返回false;若因插入而使二叉
排序树失去平衡,则要做平衡旋转处理,布尔变量taller反映T长高与否
*/
bool InsertAVL(BiTree &T, int e,bool &taller){
    if(!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){
                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树,G.M.Adelson-Velsky和E.M.Landis
#include<stdio.h>
#include<stdlib.h>
#define ElemType int

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

//平衡二叉树结点
typedef struct BiTNode{//结点结构
    ElemType 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指向新的树根结点,即旋转处理之前的右子树的根节点
*/
void L_Rotate(BiTree &p){
    BiTree R;
    R=p->rchild;//R指向P的右子树的根节点
    p->rchild=R->lchild;//R的左子树挂接为p的右子树
    R->lchild=p;
    p=R;//p指向新的根节点
}

/*对以指针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->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作右旋平衡处理

    }
}

void RightBalance(BiTree &T){
    BiTree R,Rl;
    R=T->rchild;
    switch(R->bf){
        case RH://对应于RR
            T->bf=R->bf=EH;
            L_Rotate(T);
            break;
        case LH://对应于RL
            Rl=R->lchild;
            switch(Rl->bf){
                case LH:
                    T->bf=EH;
                    R->bf=RH;
                    break;
                case EH:
                    T->bf=R->bf=EH;
                    break;
                case RH:
                    T->bf=LH;
                    R->bf=EH;
                    break;
            }
            Rl->bf=EH;
            R_Rotate(T->rchild);
            L_Rotate(T);
    }
}




/*
若在平衡的二叉排序树T中不存在和e有相同关键字的结点,则插入一个
数据元素为e的新结点,并返回true;否则返回false;若因插入而使二叉
排序树失去平衡,则要做平衡旋转处理,布尔变量taller反映T长高与否
*/
bool InsertAVL(BiTree &T, int e,bool &taller){
    if(!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){
                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;
}

void visit(BiTree T){
    printf("%d ",T->data);
}
//二叉树的中序遍历
void InOrder(BiTree T){
    if(T){
        InOrder(T->lchild);//递归遍历左子树
        visit(T);
        InOrder(T->rchild);
    }
}

void PreOrder(BiTree T){
    if(T){
        visit(T);
        PreOrder(T->lchild);//递归遍历左子树
        PreOrder(T->rchild);
    }
}


//后序遍历,销毁二叉排序树
bool DestroyBiTree(BiTree T){//删除不用&
    if(T==NULL){
        printf("空节点#\n");
        return false;
    }
    DestroyBiTree(T->lchild);
    DestroyBiTree(T->rchild);
    printf("销毁%d\n",T->data);
    free(T);
    T=NULL;//防止产生野指针
    return true;

}



int main(){
    int i;
    int a[10]={3,2,1,4,5,6,7,10,9,8};
    BiTree T=NULL;
    bool taller;
    for(i=0;i<10;i++){
        InsertAVL(T,a[i],taller);
    }

    printf("中序遍历:\n");
    InOrder(T);

    printf("\n\n可以根据前序和中序遍历的输出结果来画出平衡二叉树\n进而验证结果的正确性\n");
    printf("\n\n前序遍历:\n");
    PreOrder(T);

    printf("\n\n用完记得销毁哦(按后序遍历依次销毁)!\n");
    DestroyBiTree(T);
    return 0;
}

测试结果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值