Red-Black Tree红黑树(插入操作)

插入操作可能会造成不平衡。

为了使数平衡,AVL树需要rotate操作。那么红黑树怎么弄呢?红黑树需要:

1)recoloring

2) rotate

下面举例说明

假设x是新插入的节点。

1)标准BST树出入,插入后新节点上色为红

2)如果x不为root或者x的父节点不是黑的

   a)如果x的叔节点为红:

       1.变父节点和叔节点的颜色为黑

        2.变爷节点颜色为红

        3.爷节点变为新出入的当前结点

redBlackCase2

   b)如果叔节点是黑色的,那么按照AVL树的四种旋转情况rotate

3)如果x为root,将x的颜色变为黑


下面具体讨论叔节点为黑色时候那四种旋转:

Left Left Case:

redBlackCase3a


Left Right Case

redBlackCase3b


Right Right Case

redBlackCase3c

Right Left Case

redBlackCase3d

插入实例:插入10,20,30,15

Examples


下面是C语言实现代码:

#include <stdio.h>

struct node
{
    int data;// for data part
    char color;// for color property
    struct node* left;
    struct node* right;
    struct node* parent;
};

// leftrotate
void leftRotate(struct node** root,struct node* x)
{
    // y store the x's right child
    struct node* y=x->right;

    // update x's righit child
    x->right=y->left;
    if(x->right!=NULL)
    {
        x->right->parent=x;
    }

    // update y's parent pointer
    y->parent=x->parent;

    // if x's parent is null,make y as root of tree
    if(x->parent==NULL)
    {
        (*root)=y;
    }
    else if(x==x->parent->left)
    {
        x->parent->left=y;
    }
    else
    {
        x->parent->right=y;
    }

    y->left=x;
    x->parent=y;
}

// similar to leftrotate
void rightRotae(struct node** root,struct node* x)
{
    struct node* y=x->left;
    x->left=y->right;
    if(x->left!=NULL)
    {
        x->left->parent=x;
    }
    y->parent=x->parent;
    if(x->parent=NULL)
    {
        (*root)=y;
    }
    else if(x=x->parent->left)
    {
        x->parent->left=y;
    }
    else
    {
        x->parent->right=y;
    }

    y->right=x;
    x->parent=y;
}

void insertFixup(struct node** root,struct node* z)
{
    while(z!=*root || z->parent->color=='R')
    {
        struct node* y;

        // find uncle and stroe uncle in y
        if(z->parent=z->parent->parent->left)
            y=z->parent->parent->right;
        else
            y=z->parent->parent->left;

        // if uncle is red,do following
        // 1) change color of parent and uncle as black
        // 2) change color of grandparent as red
        // 3) move z to grandparent
        if(y->color=='R')
        {
            y->color='B';
            z->parent->color='B';
            z->parent->parent='R';
            z=z->parent->parent;
        }
        // uncle is black there is four case
        else
        {
            // left left case do following
            // 1) swap color parent and grandparent
            // 2) right rotete grandparent
            if(z=z->parent->left && z->parent=z->parent->parent->left)
            {
                char t=z->parent->color;
                z->parent->color=z->parent->parent->color;
                z->parent->parent->color=t;

                rightRotae(root,z->parent->parent);
            }

            // left right case do following
            // 1) swap color of current and grandparent
            // 2) left rotate parent
            // 3) right rotate grandparent
            if(z=z->parent->right && z->parent=z->parent->parent->left)
            {
                char t=z->color;
                z->color=z->parent->parent->color;
                z->parent->parent->color=t;

                leftRotate(root,z->parent);
                rightRotae(root,z->parent->parent);
            }

            // right right case do following
            // 1) swap color of parent and grandparent
            // 2) left rotate grandparent
            if(z=z->parent->right && z->parent=z->parent->parent->right)
            {
                \char t=z->parent->color;
                 z->parent->color=z->parent->parent->color;
                 z->parent->parent->color=t;
                 leftRotate(root,z->parent->parent);
            }

            // right left case do following
            // 1) swap color of current and grandparent
            // 2) right rotate parent
            // 3) left rotate grandparent
            if(z=z->parent->left && z->parent=z->parent->parent->right)
            {
                char t=z->color;
                z->color=z->parent->parent->color;
                z->parent->parent->color=t;

                rightRotae(root,z->parent);
                leftRotate(root,z->parent->parent);
            }
        }
    }

    (*root)->color='B';// keep root always black
}

void insert(struct node** root,int data)
{
    // allocate memory for new node
    struct node* z=(struct node*)malloc(sizeof(struct node));
    z->data=data;
    z->left=z->right=z->parent=NULL;

    // if root is null make z as root
    if(root==NULL)
    {
        z->color='B';
        (*root)=z;
    }
    else
    {
        struct node* pre=NULL;
        struct node* p=(*root);
        while(p)
        {
            pre=p;
            if(z->data>p->data)
                p=p->right;
            else
                p=p->left;
        }
        z->parent=pre;
        if(z->data>pre->data)
            pre->right=z;
        else
            pre->left=z;
        z->color='R';

        insertFixup(root,z);
    }
}

void inorder(struct node* root)
{
    if(root==NULL)
        return;
    inorder(root->left);
    printf("%d ",root->data);
    inorder(root->right);
}

int main(void)
{
    struct node* root=NULL;
    insert(&root,5);
    insert(&root,3);
    insert(&root,7);
    insert(&root,2);
    insert(&root,4);
    insert(&root,6);
    insert(&root,8);
    insert(&root,11);
    inorder(root);
    printf("Hello World!\n");
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值