1.1.1红黑树

数据结构与算法复习

1.1.1 红黑树

红黑树用在哪里?
a.hashmap
b.cfs
c.epoll
d.定时器
e.nginx
关键存在于 [key,value] 结构,强调查找。
(强查找的过程有:
        1,红黑树
        2,hash
        3,b/b+tree
        4,跳表)

首先:红黑树就是一种平衡的二叉查找树,具体具有下列五条特性:

1.节点是红色或者黑色
2.根节点是黑色
3.每个叶子的节点都是黑色
4.每个红色节点的两个子节点都是黑色的。
5.从任意节点到其每个叶子的所有路径都包含相同的黑色节点。

代码实现:
1.结点定义

typedef struct  _rbtree_node
{
    //颜色
    unsigned char color;
    
    struct _rbtree_node *right;
    struct _rbtree_node *left ;
    struct _rbtree_node *parent ;

    int key;
    void *value;
    
}rbtree_node;

2.红黑树定义

typedef struct _rbtree
{
    struct _rbtree_node *root;

    //所有叶子结点都为黑,那就让他们都指向同一个结点
    struct _rbtree_node *nil;

}rbtree;

缺点:
1)key的类型写死了
2)可复用性差

改进代码:



typedef int KEY_TYPE;
//定义宏
//简化节点结构的创建
#define RBTREE_ENTRY(name,type)\
    struct name{\
    unsigned char color;\
    struct type *right;\
    struct type *left ;\
    struct type *parent ;\
    }



typedef struct _rbtree_node
{
    //颜色
   

    KEY_TYPE key;
    void *value;
#if 0
    struct _rbtree_node *right;
    struct _rbtree_node *left ;
    struct _rbtree_node *parent ;

    unsigned char color;

#else
//使用宏可简单,多次定义多颗红黑树
    RBTREE_ENTRY(,_rbtree_node) thr_ready;
    RBTREE_ENTRY(,_rbtree_node) thr_wait;
    RBTREE_ENTRY(,_rbtree_node) thr_wait;
    RBTREE_ENTRY(,_rbtree_node) thr_exit;
 


#endif     
}rbtree_node;

typedef struct _rbtree
{
    struct _rbtree_node *root;

    //所有叶子结点都为黑,那就让他们都指向同一个结点
    struct _rbtree_node *nil;

}rbtree;



红黑树的左旋与右旋

在这里插入图片描述
左旋代码实现

//左旋
void rbtree_left_rotate(rbtree *T,rbtree_node *x){
//传入 *T目的是为了:1.判断左子树或右子树是否为叶子结点  2.判断父结点是否为根结点
    rbtree_node *y = x -> right;
//第一对
    x->right = y -> left;
    if( y->left!= T->nil)  y->left->parent = x;

    y->parent = x -> parent;

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


//第三对
    y -> left = x;
    x -> parent = y;

}

右旋代码实现(将左旋中,x和y互换,left和right互换)


//右旋
void rbtree_right_rotate(rbtree *T,rbtree_node *y){
//传入 *T目的是为了:1.判断左子树或右子树是否为叶子结点  2.判断父结点是否为根结点
    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;

}

红黑树的插入


//调整红黑树
void rbtree_insert_fixup(rbtree *T,rbtree_node *z){
    //z是插入的结点,一定是红色的
    //z是红色
    //z的父结点是红色
    //z的祖父结点是黑色
    //z的叔父结点不知道   **
    while(z->parent->color== 'r')//如果父结点的红色,必须调整
    {
        if(z->parent == z->parent->parent->left)
        {
            rbtree_node *y = z->parent->parent->right;

            if(y->color == 'r'){
                z->parent->color = 'b';
                z->parent->parent->color = 'r';
                y->color = 'b';

                z = z->parent->parent;
            }else{//y是黑色的
            
                if(z == z->parent->right)
                {
                    z = z->parent;
                    rbtree_left_rotate(T,z);
                }
            
                    z->parent->color = 'b';
                    z->parent->parent->color = 'r';

                    rbtree_right_rotate(T,z->parent->parent);
            }


        }else{

        }
        

    }
}




//插入
//插入的结点是红色的,这样才不改变红黑树的性质
void rbtree_insert(rbtree *T,rbtree_node *z)
{
    rbtree_node *x = T->root;
    rbtree_node *y = T->nil;
    while(x!=T->nil)
    {
        //y比x高一级
        //最后x会指向叶子(nil),而y就是我们要操作的结点
        y = x;
        if(z->key < x->key){
            x = x -> left;
        }else if(z->key > x -> key){
            x = x -> right;
        }else{
            //Exit
            return ;
        }
    } 

    if(y==T->nil) T->root = z;
    else{

 

    if(y->key > z->key){
        y->left = z;
    }else{
        y->right = z;
    }
   }

   z->parent = y;
   z->left = T->nil;
   z->right = T->nil;
   z->color = 'r';
}

课后作业:了解红黑树的应用
1.epoll事件管理怎么做的
2.Linux进程调度CFS
3.Nginx Timer事件管理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值