平衡二叉树(AVL树)

1、概念

平衡二叉树:是一种二叉排序树,其中每一个节点的左子树和有字数的高度差之多等于1。

平衡因子BF(Balance Factor):将二叉树上结点的左子树深度减去右子树深度的值。

最小不平衡子树:距离插入结点最近的,且平衡因子的绝对值大于1的结点为根的子树。

2、作用

我们知道,对于一般的二叉搜索树(Binary Search Tree),其期望高度(即为一棵平衡树时)为log2n,其各操作的时间复杂度(O(log2n))同时也由此而决定。但是,在某些极端的情况下(如在插入的序列是有序的时),二叉搜索树将退化成近似链或链,此时,其操作的时间复杂度将退化成线性的,即O(n)。我们可以通过随机化建立二叉搜索树来尽量的避免这种情况,但是在进行了多次的操作之后,由于在删除时,我们总是选择将待删除节点的后继代替它本身,这样就会造成总是右边的节点数目减少,以至于树向左偏沉。这同时也会造成树的平衡性受到破坏,提高它的操作的时间复杂度。

3、实现算法

/*二叉树的二叉链表结点结构定义*/
typedef struct BiTNode    /*结点结构*/
{
    int 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指向新的根结点,即旋转处理之前的右子树的根结点0*/
void L_Rotate(BiTree *p)
{
    BiTree R;
    R=(*p)->rchild;    /*R指向p的右子树根结点*/
    (*p)->rchild=R->lchild;    /*R的右子树挂接为p的右子树*/
    R->lchild=(*p);
    *p=R;    /*p指向新的根结点*/
}

#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)
    {
        /*检查T的左子树的平衡度,并作相应平衡处理*/
        case LH:    /*新结点插入在T的左孩子的左子树上,要做单右旋处理*/
            (*T)->bf=L->bf=EH;
            R_Rotate(T);
            break;
        case RH:    /*新结点插入在T的左孩子的右子树上,要做双旋转处理*/
            Lr=L->rchild;    /*Lr指向T的左孩子的右子树根*/
            switch(Lr->br)    /*修改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做右旋平衡处理*/
    }
}

#define LH +1    /*左高*/
#define EH 0     /*等高*/
#define RH -1    /*右高*/
/*对以指针T所指结点为根的二叉树做右平衡旋转处理*/
/*本算法结束时,指针T指向新的根结点*/
void RightBalance(BiTree *T)
{
    BiTree L,Ll;
    L=(*T)->rchild;    /*L指向T的右子树根结点*/
    switch(L->bf)
    {
            /*检查T的右子树的平衡度,并作相应平衡处理*/
            case RH:    /*新结点插入在T的右孩子的右子树上,要做单左旋处理*/
                (*T)->bf=L->bf=EH;
                L_Rotate(T);
                break;
            case LH:    /*新结点插入在T的右孩子的左子树上,要做双旋转处理*/
                Ll=L->lchild;    /*Ll指向T的右孩子的左子树根*/
                switch(Ll->br)     /*修改T及其右孩子的平衡因子*/
                {
                    case LH:
                        (*T)->bf=EH;
                        L->bf=RH;
                        break;
                    case EH:
                        (*T)->bf=L->bf=EH;
                        break;
                    case RH:
                        (*T)->bf=LH;
                        L->bf=EH;
                        break;
                }
                Ll->bf=EH;
                R_Rotate(&(*T)->rchild);    /*对T的右子树做右旋平衡处理*/
                L_Rotate(T);    /*对T做左旋平衡处理*/

    }
}

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

你可能感兴趣的:(构造平衡二叉树)