红黑树的创建

红黑树的性质:

1.红黑树中的节点是黑色或者红色;

2.根节点一定是黑色

3.终端节点是黑色

4.没有2个红节点互为父子关系

5.从任意节点出发到其所能到达的各个终端节点的各条路径上黑节点数目必须完全相同

红黑树的创建:节点的初始颜色为红色,共7种情况

1.空     变为黑色   结束

2.父亲节点为黑     放入   结束

3.父亲节点为红

    3.1叔叔节点为红

    父->黑   叔->黑   爷->红

    爷爷作为当前节点向上遍历

  3.2 叔叔节点为黑

    3.2.1父亲是爷爷 的左

       3.2.1.1当前节点Z是父亲的右

            父亲作为当前节点Z,

            以当前节点Z为支点左旋

       3.2.1.2 当前节点Z是父节点的左

           父->黑    爷->红

            以爷爷为支点右旋

              结束

    3.2.2父亲是爷爷的右

        3.2.2.1当前节点Z是父亲的左

            父亲作为当前节点Z

            以Z为父的右旋

        3.2.2.2当前节点Z是父亲的右

            父->黑  爷->红

            以爷爷为支点左旋

举个例子          

代码:将根设为了全局变量,所有函数都可以直接改变他的值;左旋和右旋,在原来的基础上改动了一点点,变根的情况,更新rbt。

typedef struct node1
{
    int val;
    int color;
    struct node1* pLeft;
    struct node1* pRight;
    struct node1* pFather;
} RBT;
enum COLOR {RED,BLACK};
RBT* rbt = NULL;
void RightSpin(RBT** ppTree)
{
    RBT* pTree = *ppTree;
    RBT* ptmp = pTree->pLeft;
    pTree->pLeft = ptmp->pRight;
    if(ptmp->pRight)
        ptmp->pRight->pFather = pTree;
    ptmp->pRight = pTree;
    ptmp->pFather = pTree->pFather;
    if(pTree->pFather)
    {
        if(pTree == pTree->pFather->pRight)
            pTree->pFather->pRight = ptmp;
        else
            pTree->pFather->pLeft = ptmp;
    }
    else
        rbt = ptmp;
    pTree->pFather = ptmp;
}
void LeftSpin(RBT** ppTree)
{
    RBT* pTree = *ppTree;
    RBT* ptmp = pTree->pRight;
    pTree->pRight = ptmp->pLeft;
    if(ptmp->pLeft)
        ptmp->pLeft->pFather = pTree;
    ptmp->pLeft = pTree;
    ptmp->pFather = pTree->pFather;
    if(pTree->pFather)
    {
        if(pTree == pTree->pFather->pRight)
            pTree->pFather->pRight = ptmp;
        else
            pTree->pFather->pLeft = ptmp;
    }
    else
        rbt = ptmp;
    pTree->pFather = ptmp;
}
RBT* Find(RBT* pRBT,int num)
{
    if(pRBT == NULL) return NULL;
    while(pRBT)
    {
        if(pRBT->val == num)
            return NULL;
        else if(pRBT->val > num)
        {
            if(pRBT->pLeft)
                pRBT = pRBT->pLeft;
            else
                return pRBT;
        }
        else
        {
            if(pRBT->pRight)
                pRBT = pRBT->pRight;
            else
                return pRBT;
        }
    }
}
RBT* GetUncle(RBT* ptmp)
{
    if(ptmp->pFather == ptmp->pFather->pFather->pLeft)
        return ptmp->pFather->pFather->pRight;
    else
        return ptmp->pFather->pFather->pLeft;
}
void InsertNode(RBT* pRBT, int num)
{
    RBT* ptmp = (RBT*)malloc(sizeof(RBT));
    ptmp->val = num;
    ptmp->color = RED;
    ptmp->pLeft = NULL;
    ptmp->pRight = NULL;
    ptmp->pFather = NULL;
    //查找
    RBT* pfather = Find(pRBT,num);
    //空树
    if(pRBT == NULL)
    {
        ptmp->color = BLACK;
        rbt = ptmp;
        return;
    }
    if(pfather->val > num)
        pfather->pLeft = ptmp;
    else
        pfather->pRight = ptmp;
    ptmp->pFather = pfather;
    //父节点为黑色
    if(pfather->color == BLACK)
    {
        return;
    }
    RBT* pGrandfather = NULL;
    RBT* pUncle = NULL;
    //父节点为红色
    while(pfather->color == RED)
    {
        pGrandfather = pfather->pFather;
        pUncle = GetUncle(ptmp);
        //叔叔为红色
        if(pUncle != NULL && pUncle->color == RED )
        {
            pfather->color = BLACK;
            pUncle->color = BLACK;
            pGrandfather->color = RED;
            ptmp = pGrandfather;
            pfather = ptmp->pFather;

            if(pfather == NULL)
            {
                ptmp->color = BLACK;
                return;
            }
            continue;
        }
        //没有叔叔或叔叔是黑色
        if(pUncle == NULL || pUncle->color == BLACK)
        {
            //父为爷左
            if(pfather == pGrandfather->pLeft)
            {
                //当前节点为父右
                if(ptmp == pfather->pRight)
                {
                    ptmp = pfather;
                    LeftSpin(&ptmp);
                    pfather = ptmp->pFather;
                    continue;
                }
                //当前节点为父左
                if(ptmp == pfather->pLeft)
                {
                    pfather->color = BLACK;
                    pGrandfather->color = RED;
                    RightSpin(&pGrandfather);
                    break;
                }
            }
            if(pfather == pGrandfather->pRight)
            {
                if(ptmp == pfather->pLeft)
                {
                    ptmp = pfather;
                    RightSpin(&ptmp);
                    pfather = ptmp->pFather;
                    continue;
                }
                if(ptmp == pfather->pRight)
                {
                    pfather->color = BLACK;
                    pGrandfather->color = RED;
                    LeftSpin(&pGrandfather);
                    break;
                }
            }
        }
    }
    rbt->color =BLACK;
}

 

转载于:https://www.cnblogs.com/Lune-Qiu/p/9045849.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值