平衡二叉树的插入、删除

#include <iostream>
#include <algorithm>
#include <vector>
//平衡二叉排序树
struct NODE
{
    int val;
    int bf;//平衡因子,当所有节点的平衡因子为-1、0、1时,此二叉排序树是平衡二叉排序树
    NODE *lchild, *rchild;
};

void R_Rotate(NODE **p)
{
    //右旋
    NODE *q = (*p)->lchild;
    (*p)->lchild = q->rchild;
    q->rchild = *p;
    *p = q;
}

void L_Rotate(NODE **p)
{
    //左旋
    NODE *q = (*p)->rchild;
    (*p)->rchild = q->lchild;
    q->lchild = *p;
    *p = q;
}

void LeftBalance(NODE **T)
{
    //对以指针T所指节点为根的二叉树做左平衡旋转处理
    //此时T->bf > 1
    //需考察T->lchild->bf与T->bf符号相同与不相同两种情况
    NODE *L = (*T)->lchild;
    switch(L->bf)
    {
    case 1:
        {
            //新插入的节点在T的左孩子的左子树上
            //符号相同,直接右旋
            L->bf = (*T)->bf = 0;
            R_Rotate(T);
            break;
        }
    case -1:
        {
            //新插入节点在T的左孩子的右子树上
            //符号不同,需先对L左旋,调整L->bf与T->bf符号相同,再对T右旋
            NODE *Lr = L->rchild;

            switch (Lr->bf)
            {
            case 1:
                {
                    L->bf = 0;
                    (*T)->bf = -1;
                    break;
                }
            case -1:
                {
                    L->bf = 1;
                    (*T)->bf = 0;
                    break;
                }
            case 0:
                {
                    (*T)->bf = L->bf = 0;
                    break;
                }
            default:
                break;
            }
            Lr->bf = 0;
            L_Rotate(&(*T)->lchild);
            R_Rotate(T);

            break;
        }
    case 0:
        {
            (*T)->bf = 1;
            L->bf = -1;
            R_Rotate(T);
            break;
        }
    }
}

void RightBalance(NODE **T)
{
    //对以指针T所指节点为根的二叉树做右平衡旋转处理
    //此时T->bf < -1
    //需考察T->lchild->bf与T->bf符号相同与不相同两种情况

    NODE *R = (*T)->rchild;
    switch (R->bf)
    {
    case 1:
        {
            //新插入的节点在T右子树的左孩子上
            //R->bf与T->bf符号不同,需进行双旋转
            NODE *rl = R->lchild;
            switch (rl->bf)
            {
            case 1:
                {
                    R->bf = -1;
                    (*T)->bf = 0;
                    break;
                }
            case -1:
                {
                    R->bf = 0;
                    (*T)->bf = 1;
                    break;
                }
            case 0:
                {
                    (*T)->bf = R->bf = 0;
                    break;
                }
            default:
                break;
            }
            rl->bf = 0;
            R_Rotate(&(*T)->rchild);
            L_Rotate(T);
            break;
        }
    case -1:
        {
            //新插入的节点在T右子树的右还是上
            //R->bf与T->bf符号相同,直接旋转
            (*T)->bf = R->bf = 0;
            L_Rotate(T);
            break;
        }
    case 0:
        {
            (*T)->bf = -1;
            R->bf = 1;
            L_Rotate(T);
            break;
        }
    default:
        break;
    }
}

//taller用于记录树是否长高,即是否插入成功
//如果插入成功后,需递归回溯进行平衡调整,修改BF值
int InsertAVL(NODE **T, int key, int &taller)
{
    if(!(*T))
    {
        *T = new NODE;
        (*T)->val = key;
        (*T)->bf = 0;
        (*T)->lchild = (*T)->rchild = NULL;
        taller = 1;
    }
    else
    {
        if(key == (*T)->val)
        {
            //树中已经有key了,插入失败
            taller = 0;
            return 0;
        }
        else if(key < (*T)->val)
        {
            if(!InsertAVL(&(*T)->lchild, key, taller))
            {
                //左子树中插入失败
                return 0;
            }
            else
            {
                //左子树中插入成功
                if(taller)
                {
                    //树长高, 此时需修改T的BF
                    switch((*T)->bf)
                    {
                        //判断当前*T的BF值
                    case 0:
                        {
                            //原本左右子树等高,现因左子树增高而树增高
                            (*T)->bf = 1;
                            break;
                        }
                    case 1:
                        {
                            //原本左子树比右子树高,需作平衡处理
                            LeftBalance(T);
                            taller = 0;
                            break;
                        }
                    case -1:
                        {
                            //原本右子树比左子树高,现在左子树增高,左右子树等高
                            (*T)->bf = 0;
                            taller = 0;
                            break;
                        }
                    default:
                        break;
                    }
                }
            }
        }
        else
        {
            if(!InsertAVL(&(*T)->rchild, key, taller))
            {
                //插入失败
                return false;
            }
            else
            {
                if(taller)
                {
                    switch((*T)->bf)
                    {
                    case 0:
                        {
                            //原本等高,现在右子树比左子树高
                            (*T)->bf = -1;
                            break;
                        }
                    case 1:
                        {
                            //原本左子树高,现在等高
                            (*T)->bf = 0;
                            taller = 0;
                            break;
                        }
                    case -1:
                        {
                            //原本右子树高,现在右边插入,需调整
                            RightBalance(T);
                            taller = 0;
                            break;
                        }
                    default:
                        break;
                    }
                }
            }
        }
    }
}
//smaller用于标记树是否变矮
int DeleteAVL(NODE **T, int key, int &smaller)
{
    if(!*T)
    {
        return 0;
    }
    else if((*T)->val > key)
    {
        //左子树中删除
        if(!DeleteAVL(&(*T)->lchild, key, smaller))
        {
            return 0;
        }
        else
        {
            if(smaller)
            {
                //如果左子树高度降低了,需考察当前结点的高度,看是否进行旋转
                switch ((*T)->bf)
                {
                case 0:
                    {
                        (*T)->bf = -1;
                        smaller = 0;//左子树的高度本身没有变化,任然是当前结点右子树那么高
                        break;
                    }
                case 1:
                    {
                        (*T)->bf = 0;
                        break;
                    }
                case -1:
                    {
                        RightBalance(T);
                        break;
                    }
                default:
                    break;
                }
            }
        }
    }
    else if((*T)->val < key)
    {
        //在右子树中进行删除
        if(!DeleteAVL(&(*T)->rchild, key, smaller))
        {
            return 0;
        }
        else
        {
            if(smaller)
            {
                switch ((*T)->bf)
                {
                case 0:
                    {
                        (*T)->bf = 1;
                        smaller = 0;//仍然与当前节点的左子树那么高
                        break;
                    }
                case 1:
                    {
                        LeftBalance(T);
                        break;
                    }
                case -1:
                    {
                        (*T)->bf = 0;
                        break;
                    }
                default:
                    break;
                }
            }
        }
    }
    else
    {
        //找到需要删除的节点
        NODE *p = *T;
        if(p->lchild && p->rchild)
        {
            //此节点有两个孩子,使用中序遍历的前驱来进行替换
            NODE *q = p;
            NODE *s = p->lchild;
            while(s->rchild)
            {
                q = s;
                s = s->rchild;
            }
            if(q != p)
            {
                p->val = s->val;
                s->val = key;
                if(!DeleteAVL(&(*T)->lchild, key, smaller))
                {
                    return 0;
                }
                else
                {
                    if(smaller)
                    {
                        switch ((*T)->bf)
                        {
                        case 0:
                            {
                                (*T)->bf = -1;
                                smaller = 0;//高度没有变化,仍然是右子树那么高
                                break;
                            }
                        case 1:
                            {
                                (*T)->bf = 0;
                                break;
                            }
                        case -1:
                            {
                                RightBalance(T);
                                break;
                            }
                        default:
                            break;
                        }
                    }
                }
            }
            else
            {
                //左孩子没有右孩子
                p->val = s->val;
                p->lchild = s->lchild;
                delete s;
                s = NULL;
                switch (p->bf)
                {
                case 0:
                    {
                        p->bf = -1;
                        smaller = 0;//高度并没有降低
                        break;
                    }
                case 1:
                    {
                        p->bf = 0;
                        smaller = 0;//高度没有降低
                        break;
                    }
                case -1:
                    {
                        smaller = 1;//高度降低
                    }
                default:
                    break;
                }
            }
        }
        else
        {
            //此节点有1个或0个孩子
            smaller = 1;
            if((*T)->lchild)
            {
                //有左孩子,没有右孩子
                *T = (*T)->lchild;
            }
            else if((*T)->rchild)
            {
                //有右孩子,没有左孩子
                *T = (*T)->rchild;
            }
            else
            {
                //有0个孩子
                *T = NULL;
            }
            delete p;
            p = NULL;
        }
        return 1;
    }
}
int main(int nArgs, char* pArg[])
{
    int a[10] = {3, 2, 1, 4, 5, 6, 7, 10, 9, 8};
    int taller = 0;
    NODE *T = NULL;
    for(int i = 0; i < 10; ++i)
    {
        InsertAVL(&T, a[i], taller);
    }
    int smaller = 0;
    std::cout << DeleteAVL(&T, 2, smaller) << std::endl;
    std::cout << DeleteAVL(&T, 3, smaller) << std::endl;
    std::cout << DeleteAVL(&T, 7, smaller) << std::endl;
    system("pause");
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值