红黑树

红黑树:

性质:
1、每个节点是红的或者黑的
2、根节点是黑的
3、每个叶子节点是黑的
4、如果一个节点是红的,则它两个孩子都是黑的
5、对每个节点,从该节点到其子孙节点的所有路径上的包含相同数目的黑节点
6、每个叶子节点都隐藏,并且为黑色
应用:
1、Linux进程调度CFS
2、Nginx Timer事件管理
3、Epoll事件块的管理
红黑树:

在这里插入图片描述

数据结构:
typedef int KEY_TYPE;

typedef struct _rbtree_node
{
    unsigned char color;
    struct _rbtree_node *right;
    struct _rbtree_node *left;
    struct _rbtree_node *parent;
    KEY_TYPE key;
    void *value;
}rbtree_node;


typedef struct _rbtree
{
    rbtree_node *root;
    rbtree_node *nil;
}rbtree;
红黑树结点旋转:

在这里插入图片描述

在这里插入图片描述

//红黑树的旋转
//左旋
void rbtree_left_rotate(rbtree *T, rbtree_node *x)
{
    rbtree_node *y = x->right;  //将x的右子树赋值给y做第一步旋转

    x->right = y->left;     //1、x的右子树等于y的左子树
    if(y->left != T->nil)   //2、如果y的左子树不是叶子节点则y的左子树的父节点是x
    {
        y->left->parent = x;
    }

    y->parent = x->parent;      //3、y的父节点等于x的父节点
    if(x->parent == T->nil)     //4、判断x是否位为根节点
    {
        T->root = y;
    }
    else if(x == x->parent->left)
    {
        x->parent->left = y;
    }
    else
    {
        x->parent->right = y;
    }

    y->left = x;        //5、最后拼接将y的左子树赋给x,x的父节点赋给y,完成旋转
    x->parent = y;      
}
//右旋与左旋同理
void rbtree_right_rotate(rbtree *T, rbtree_node *y)
{
    rbtree_node *x = y->left;

    y->left = x->right;
    if(x->right != T->nil)
    {
        x->right->parent = y;
    }

    x->parent = y->parent;
    if(y->parent == T->nil)
    {
        T->root = x;
    }
    else if(y == y->parent->right)
    {
        y->parent->right = x;
    }
    else
    {
        y->parent->left = x;
    }

    x->right = y;
    y->parent = x;
}
红黑树的插入及其插入后的位置修正:
1、当前新插入节点node是红色的,node的父节点是红色,node的祖父节点肯定是黑色的,叔父节点可能是红色也可能是黑色
2、当前节点永远是红色的
3、当叔父节点是红色时不需要旋转,只改变颜色(叔父节点和父节点黑色高度一样)
4、当叔父节点是黑色时且当前节点是右子树,左旋
5、当叔父节点是黑色时且当前节点是左子树,右旋
//插入后的修复
void rbtree_insert_fix(rbtree *T, rbtree_node *node)
{
    while(node->parent->color == RED)
    {
        if(node->parent == node->parent->parent->left)
        {
            //当node的父节点是右子树时
            rbtree_node *uncle_node = node->parent->parent->right;
            if(uncle_node->color == RED)
            {
                node->parent->color = BLACK;
                uncle_node->color = BLACK;
                node->parent->parent->color = RED;

                node = node->parent->parent;
            }
            else
            {
                //叔父节点是黑色时且为右子树,左旋
                if(node == node->parent->right)
                {
                    node = node->parent;
                    rbtree_left_rotate(T, node);
                }

                //叔父节点是黑色时且为左子树,右旋
                node->parent->color = BLACK;
                node->parent->parent->color = RED;
                rbtree_right_rotate(T, node->parent->parent);
            }
        }
        else
        {
            //当node的父节点是左子树时
            rbtree_node *uncle_node = node->parent->parent->left;
            if(uncle_node->color == RED)
            {
                node->parent->color = BLACK;
                uncle_node->color = BLACK;
                node->parent->parent->color = RED;

                node = node->parent->parent;
            }
            else
            {
                if(node == node->parent->left)
                {
                    node = node->parent;
                    rbtree_right_rotate(T, node);
                }

                node->parent->color = BLACK;
                node->parent->parent->color = RED;
                rbtree_left_rotate(T, node->parent->parent);
            }
        }
    }

    T->root->color = BLACK;
}

//红黑树的插入
void rbtree_insert(rbtree *T, rbtree_node *node)
{
    rbtree_node *y = T->nil;
    rbtree_node *x = T->root;

    while(x != T->nil)  //x循环到叶子节点
    {
        y = x;
        if(node->key < x->key)
        {
            x = x->left;
        }
        else if(node->key > x->key)
        {
            x = x->right;
        }
        else
        {
            return ;
        }
    }

    node->parent = y;
    if(y == T->nil)
    {
        T->root = node;     //只有一个节点时新插入节点就是根节点
    }
    else if(node->key < y->key)
    {
        y->left = node;
    }
    else
    {
        y->right = node;
    }

    node->left = T->nil;
    node->right = T->nil;
    node->color = RED;
    
    rbtree_insert_fix(T, node);
}
红黑树的删除:

如果删除节点27,则172是覆盖节点,206是删除节点,224是轴心节点
在这里插入图片描述

1、如果要删除的节点node没有左右子树直接将该节点删除
2、node节点有左子树或者右子树,将node节点转移到其父节点上,把node节点删除
3、node节点有左子树且有右子树则需分多种情况讨论(y为黑色,x是y的右子树。如果x是红色,则把x赋为黑色,反之则进行调整)
	a、当前节点的兄弟节点是红色的
	b、当前节点的兄弟节点是黑色的,而且兄弟节点的两个孩子节点都是黑色的
	c、当前节点的兄弟节点是黑色的,而且兄弟节点的左孩子是红色的,右孩子是黑色的
	d、当前节点的兄弟节点是黑色的,而且兄弟节点的右孩子是红色的
//找最小节点
rbtree_node *rbtree_mini(rbtree *T, rbtree_node *node)
{
    while(node->left != T->nil)
    {
        node = node->left;
    }

    return node;
}

//找最大节点
rbtree_node *rbtree_max(rbtree *T, rbtree_node *node)
{
    while(node->right != T->nil)
    {
        node = node->right;
    }

    return node;
}

//寻找继承节点
rbtree_node *rbtree_successor(rbtree *T, rbtree_node *node)
{
    rbtree_node *y = node->parent;

    //分存在左右子树进行讨论
    if(node->right != T->nil)
    {
        return rbtree_mini(T, node->right);
    }

    while((y != T->nil) && (node == y->right))
    {
        node = y;
        y = y->parent;
    }

    return y;
}

//节点删除修复
void rbtree_delete_fix(rbtree *T, rbtree_node *x)
{
    while((x != T->root) && (x->color == BLACK))
    {
        //判断x节点是否为左子树,是的话兄弟节点是右子树,反之则相反
        if(x == x->parent->left)
        {
            rbtree_node *brother_node = x->parent->right;
            if(brother_node->color == RED)
            {
                brother_node->color = BLACK;
                x->parent->color = RED;

                //如果兄弟节点是红色,则调整兄弟节点为黑色,父节点为红色,进行左旋
                rbtree_left_rotate(T, x->parent);
                brother_node = x->parent->right;
            }

            if((brother_node->left->color == BLACK) && (brother_node->right->color == BLACK))
            {
                brother_node->color = RED;
                x = x->parent;
            }
            else
            {
                if(brother_node->right->color == BLACK)
                {
                    //如果兄弟节点的右孩子是黑色,则调整其左孩子为黑色,自己则为红色,进行右旋
                    brother_node->left->color = BLACK;
                    brother_node->color = RED;
                    
                    rbtree_right_rotate(T, brother_node);
                    brother_node = x->parent->right;
                }

                //反之调整其父节点为黑色,右孩子为黑色,自身为父节点颜色,左旋
                brother_node->color = x->parent->color;
                x->parent->color = BLACK;
                brother_node->right->color = BLACK;
                rbtree_left_rotate(T, x->parent);
                x = T->root;
            }
            
        }
        else
        {
            //x节点是右子树时,与上同理
            rbtree_node *brother_node = x->parent->left;
            if(brother_node->color == RED)
            {
                brother_node->color = BLACK;
                x->parent->color = RED;
                rbtree_right_rotate(T, x->parent);

                brother_node = x->parent->left;
            }
            
            if((brother_node->left->color == BLACK) && (brother_node->right->color == BLACK))
            {
                brother_node->color = RED;
                x = x->parent;
            }
            else
            {
                if(brother_node->left->color == BLACK)
                {
                    brother_node->right->color == BLACK;
                    brother_node->color = RED;
                    rbtree_left_rotate(T, brother_node);
                    brother_node = x->parent->left;
                }

                brother_node->color = x->parent->color;
                x->parent->color = BLACK;
                brother_node->left->color = BLACK;
                rbtree_right_rotate(T, x->parent);
                x = T->root;
            }
        }
    }

    x->color = BLACK;
}

//红黑树节点删除
rbtree_node *rbtree_delete(rbtree *T, rbtree_node *node)
{
    rbtree_node *y = T->nil;
    rbtree_node *x = T->nil;

    //判断node是否有左子树或右子树
    if((node->left == T->nil) || (node->right == T->nil))
    {
        y = node;
    }
    else
    {
        y = rbtree_successor(T, node);  //寻找继承节点
    }

    //转移节点
    if(y->left != T->nil)
    {
        x = y->left;
    }
    else if(y->right != T->nil)
    {
        x = y->right;
    }

    x->parent = y->parent;
    if(y->parent == T->nil)
    {
        T->root = x;
    }
    else if(y == y->parent->left)
    {
        y->parent->left = x;
    }
    else
    {

        y->parent->right = x;
    }


    if(y != node)
    {
        node->key = y->key;
        node->value = y->value;
    }
    
    //如果当前节点是黑色即要保持黑高则要进行修复
    if(y->color == BLACK)
    {
        rbtree_delete_fix(T, x);
    }

    return y;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值