二叉树与红黑树

1.红黑树用途

        a.key->value 查找功能

        b.利用红黑树的中序遍历是顺序的

        例子:nigix,定时器,cfs,内存管理

2.性质

        1. 每个结点是红的或者黑的

        2. 根结点是黑的

        3. 每个叶子结点是黑的(特殊处理,让其指向一个通用的叶子节点即可)

        4. 如果一个结点是红的,则它的两个儿子都是黑的

        5. 对每个结点,从该结点到其子孙结点的所有路径上的 包含相同数目的黑结点

        (所有叶子节点都隐藏,并且叶子节点为黑色)

3.红黑树基本结构

        

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

typedef struct _rb_tree{
    rbtree_node *root;
    rbtree_node *nil;
}rb_tree;

4.红黑树的左右旋转

 左右旋转的代码实现

void _left_rotate(rbtree * T,rbtree_node *x){
    //左旋三个方向,六个指针改变
    rbtree_node * y = x->right;
    //第一个方向
    x->right = y->left;
    //y的左子树不是叶节点的情况
    if(y->left != T->nil){
        y->left->parent = x;
    }
    y->parent = x->parent;
    //x为根的情况
    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;
}

void _right_rotate(rbtree *T,rbtree_node *y){
    rbtree_node * x = y->left;
    y->left = x->right;
    //y的左子树不是叶节点的情况
    if(x->right != T->nil){
        x->right->parent = y;
    }
    x->parent = y->parent;
    //x为根的情况
    if(x->parent == T->nil){
        T->root = x;
    }
    else if(y == y->parent->left){
        y->parent->left = x;
    }
    else{
        y->parent->left = x;
    }
    x->right = y;
    y->parent = x;
}

5.红黑树的添加

        要点:分清左右子树的情况

        然后再细分成三类,旋转,调整

        


void _left_rotate(rbtree * T,rbtree_node *x){
    //左旋三个方向,六个指针改变
    rbtree_node * y = x->right;
    //第一个方向
    x->right = y->left;
    //y的左子树不是叶节点的情况
    if(y->left != T->nil){
        y->left->parent = x;
    }
    y->parent = x->parent;
    //x为根的情况
    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;
}

void _right_rotate(rbtree *T,rbtree_node *y){
    rbtree_node * x = y->left;
    y->left = x->right;
    //y的左子树不是叶节点的情况
    if(x->right != T->nil){
        x->right->parent = y;
    }
    x->parent = y->parent;
    //x为根的情况
    if(x->parent == T->nil){
        T->root = x;
    }
    else if(y == y->parent->left){
        y->parent->left = x;
    }
    else{
        y->parent->left = x;
    }
    x->right = y;
    y->parent = x;
}
//并且插入当前节点前肯定是一颗红黑树
//调整只关心父节点和祖父节点以及叔节点
//先从父节点是左子树开始思考
//是右子树的情况是对称的
void rbtree_insert_fixup(rbtree * T,rbtree_node *z){
    //只有父节点是红色才可能会出现违背红黑树性质的情况
    //这个时候祖父节点一定是黑色,故不需要考虑
    //不断的迭代往上递归
    while(z->parent->color == RED){
        //叔父节点是红色
        //叔父节点是黑色(即叶节点),当前节点父节点左子树
        //叔父节点是黑色,当前节点父节点右子树
        if(z->parent == z->parent->parent->left){
            rbtree_node *y = z->parent->parent->right;
            //叔父为红的情况
            if(y->color == RED){
                z->parent->color = BLACK;
                y->color = BLACK;
                z->parent->parent->color = RED;
                //继续向上查询
                z = z->parent->parent;
            }
            else{
                //统一成只有一边有节点的形式
                if(z == z->parent->right){
                    z = z->parent;
                    _left_rotate(T,z);
                }
                z->parent->color = BLACK;
                z->parent->parent->color = RED;
                _right_rotate(T,z->parent);
            }
        }
        else{
            rbtree_node * y = z->parent->parent->left;
            if(y->color == RED){
                z->parent->color = BLACK;
                y->color = BLACK;
                z->parent->parent->color = RED;
                z = z->parent->parent;
            }
            else{
                if(z == z->parent->left){
                    z = z->parent;
                    _right_rotate(T,z);
                }
                z->parent->color = BLACK;
                z->parent->parent->color = RED;
                _rleft_rotate(T,z->parent);
            }
        }  
    }
}


void rbtree_insert(rbtree * T,rbtree_node *z){
    //y始终是x的父节点
    rbtree_node *y = T->nil;
    rbtree_node *x = T->root;
    while(x != T->nil){
        if(z->key < x->key){
            y = x;
            x = x->left;
        }
        else if(z->key > x->key){
            y = x;
            x = x->right;
        }
        else{
            //相等的情况不做处理
            return;
        }
    }
    z->parent = y;
    //插入节点是根节点的情况(即插入前树为空的情况)
    if(y == T->nil){
        T->root = z;
    }
    else if(z->key < y->key){
        y->left = z;
    }
    else{
        y->right = z;
    }
    z->left = T->nil;
    z->right = T->nil;
    //上红色
    z->color = RED;

    rbtree_insert_fixup(T,z);
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值