红黑树及插入代码

场景:

hashmap、cfs、epoll、定时器、nginx
强查找:红黑树、hash、b/b++树、跳表
树定义:

typedef struct _rbtree_node {
    //rbtree
    unsigned char color;
    struct rbtree_node *parent;
    struct rbtree_node *left;
    struct rbtree_node *right;
    // end


    KEY_TYPE key; 

    // value
    //
} rbtree_node;


struct rbtree {
    rbtree_node *root;
    rbtree_node *nil; // NULL节点,所有的叶子节点和根节点的指向
};

旋转:

在这里插入图片描述

红黑树性质被破坏时,就会产生旋转
左旋和右旋是可逆的

左旋:

在这里插入图片描述

void rbtree_left_rotate(rbtree *T, rbtree_node *x) {
    // NULL --> T->nil
    if (x == T->nil) return ;
    rbtree_node *y = x->right;
	// 步骤1
    x->right = y->left;
    if (y->left != T->nil) {
        y->left->parent = x;
    }

    // 步骤2
    y->parent = x->parent;
    if (x->parent == T->nil) {//x为根节点
        T->root = y;
    } else if (x == x->parent->left) {//x为父节点的左子树
        x->parent->left = y;
    } else {//x为父节点的右子树
        x->parent->right = y;
    }

    // 步骤3
    y->left = x;
    x->parent = y;

}

右旋:

把左旋代码中的所有x改为y,y改为x,left改为right,right改为left;

// x --> y, y -->x 
// left --> right, right --> left

void rbtree_right_rotate(rbtree *T, rbtree_node *y) {
    // NULL --> T->nil
    if (y == T->nil) return ;
    // 1
    rbtree_node *x = y->left;

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

    // 2
    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;
    }

    // 3
    y->left = x;
    x->parent = y;

}

插入:

插入的所有的值都会在最底层
红黑树没有对相同值的节点处理:对于业务场景丢弃或者是加一个eps
红黑树在插入任何一个节点之前就已经是红黑树了,用数学的归纳法,所以插入一个节点只能是红的(红色不改变黑高)
在这里插入图片描述

void rbtree_insert(rbtree *T, rbtree_node *z) {

    rbtree_node *y = T->nil;
    rbtree_node *x = T->root;//y指向x的前一个节点

	//找到要插入哪个节点下面
    while (x != T->nil) {
        y = x;
        if (z->key < x->key) {
            x = x->left;
        } else if (z->key > x->key) {
            x = x->right;
        } else { //对于业务场景丢弃
        }
    }

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

    // z --> 
    z->color = RED;
    z->left = T->nil;
    z->right = T->nil;

    // 再验证是否为红黑树,进行翻转

}

翻转红黑树
在这里插入图片描述
上面的操作始终没有影响黑高

while (z->parent->color == RED) { 
     if (z->parent == z->parent->parent->left) {
		y = z->parent->parent->right; //叔节点
            if (y->color == RED) {
                z->parent->color = BLACK;
                z->parent->parent->color = RED;
                y->color = BLACK;

                z = z->parent->parent; //z始终是红的
            }
 }

在这里插入图片描述

                z->parent->color = BLACK;
                z->parent->parent->color = RED;
                rbtree_right_rotate(T, z->parent->parent);

在这里插入图片描述
上面操作的结果只是暂时的状态,暂时态就变为了状态3

                if (z = z->parent->right) {
                    z = z->parent;
                    rbtree_left_rotate(T, z);//这样就变为了状态3
                }

完整代码:



#define RED     0
#define BLACK   1

typedef int KEY_TYPE;

typedef struct _rbtree_node {
    //rbtree
    unsigned char color;
    struct rbtree_node *parent;
    struct rbtree_node *left;
    struct rbtree_node *right;
    // end


    KEY_TYPE key; 

    // value
    //
} rbtree_node;


struct rbtree {
    rbtree_node *root;
    rbtree_node *nil; // NULL节点,所有的叶子节点和根节点的指向
};

// rotate 

void rbtree_left_rotate(rbtree *T, rbtree_node *x) {
    // NULL --> T->nil
    if (x == T->nil) return ;
    // 1
    rbtree_node *y = x->right;

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

    // 2
    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;
    }

    // 3
    y->left = x;
    x->parent = y;

}

// x --> y, y -->x 
// left --> right, right --> left

void rbtree_right_rotate(rbtree *T, rbtree_node *y) {
    // NULL --> T->nil
    if (y == T->nil) return ;
    // 1
    rbtree_node *x = y->left;

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

    // 2
    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;
    }

    // 3
    y->left = x;
    x->parent = y;

}


void rbtree_insert_fixup(rbtree *T, rbtree_node *z) {
    //始终插入的节点一直是红色,在向上回溯的时候,z一直是红色的
    // z->color == RED
    // z->parent->color == RED

    // z--> RED
    while (z->parent->color == RED) { // 

        if (z->parent == z->parent->parent->left) {

            y = z->parent->parent->right; //

            if (y->color == RED) {

                z->parent->color = BLACK;
                z->parent->parent->color = RED;
                y->color = BLACK;

                z = z->parent->parent; //z始终是红的
            } else { // 

                if (z = z->parent->right) {
                    z = z->parent;
                    rbtree_left_rotate(T, z);
                }

                z->parent->color = BLACK;
                z->parent->parent->color = RED;
                rbtree_right_rotate(T, z->parent->parent);

            }


        } 

    }


}

void rbtree_insert(rbtree *T, rbtree_node *z) {

    rbtree_node *y = T->nil;
    rbtree_node *x = T->root;//y指向x的前一个节点

    while (x != T->nil) {

        y = x;

        if (z->key < x->key) {
            x = x->left;
        } else if (z->key > x->key) {
            x = x->right;
        } else { //Exist

        }

    }

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

    // z --> 
    z->color = RED;
    z->left = T->nil;
    z->right = T->nil;

    // 

}




  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值