什么是红黑树以及由来
这里先了解红黑树的由来,既然出现红黑树这种数据结构肯定是原本的数据结构不满足已知的问题所致。
二叉搜索树:
起初最开始为二叉搜索树,这是最简单的树型结构。
其定义:或者是一棵空树,或者是具有下列性质的二叉树:
若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
它的左、右子树也分别为二叉排序树。
但是其面临最基本的问题:
可以看到,在这种情况下,二叉搜索树退化成了链表!!!这时候查询、插入和删除一个元素的时候,时间复杂度变成了O(n),显然这是不能接受的。出现这种情况情况的原因是二叉搜索树没有自平衡的机制,所以就有了平衡二叉树的概念。
平衡二叉树
定义:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。简而言之就是在二叉搜索树的基础上加上平衡机制来解决上面出现的问题。
推荐大家看看这个二叉树讲解,一篇文章解决!

但是,其仍然有很大的问题,最大的问题就是太麻烦,平衡二叉树的定义过于严格,导致每次插入或者删除一个元素之后,都要去维护二叉树整体的平衡,这样产生额外的代价又太大了。大家也不想再插入元素的时候等很长时间来处理吧,基于此我们慢慢提出来红黑树的原型-2-3树!
2-3树
大家看看下边推荐的文章,里边讲解基本原理,基本大家看懂了2-3树,红黑树也就懂了!
大家看看这个,简单易懂帮大家整理最好的!
红黑树
进入正题,红黑树性质如下:
性质1:每个节点要么是黑色,要么是红色。
性质2:根节点是黑色。
性质3:每个叶子节点(NIL)是黑色。
性质4:每个红色结点的两个子结点一定都是黑色。
性质5:任意一结点到每个叶子结点的路径都包含数量相同的黑结点。
其中删除插入操作种类很多,推荐看这个简单入手
图解红黑树插入删除的各种情况
代码
红黑树节点定义:
其中key为节点中的值。
typedef int KEY_TYPE;
typedef struct _rbtree_node{
unsigned char color;
struct _rbtree_node *left;
struct _rbtree_node *right;
struct _rbtree_node *parent;
KET_TYPE key;
void *value;
}rbtree_node;
定义红黑树:
root为指向这棵树的根节点;
nil为空节点,方便后续跟叶子节点作比较而来判断叶子节点使用;
typedef struct _rbtree{
typedef struct *root;
typedef struct *nil;
};
左旋操作:

void _left_rotate(rbtree *T,rbtree *x){
rbtree_node *y=x->right;
x->right=y->right;
if(y->right!=T->nil){//如果节点y的左子树存在再赋值
y->right->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;
}
右旋操作
void _right_rotate(rbtree *T,rbtree *x){
rbtree_node *x=y->left;
y->left=x->left;
if(x->right!=T->nil){//如果节点y的左子树存在再赋值
x->right->parent=y;
}
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;
}
x->right=y;
y->parent=x;
}
插入节点
寻找插入位置:
void rbtree_insert(rbtree *T,rbtree_node *z){
rbtree_node *x=T->root;
rbtree_node *y=T->nil;
while(x!=T->nil){
y=x;
if(z->key<x->key){
x=x->left;
}else if(z->key>x->key){
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_flxup(T,z);//调整函数
}
插入调整(左右旋转,变色处理):
这里边一共三种情况,如果不懂大家可以看看我推荐的文章。
void rbtree_insert_flxup(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=BALACK;
y->color=BALACK;
z->parent->parent->color=REN;
z=z->parent;
}else{
if(z==z->parent->right){
z=z->parentp;
_left_rotate(T,z);
}
z->parent->color=BALACK;
z->parent->parent->color=RED;
_right_rotate(T,z->parent->parent);
}
}
else{
rbtree_node *y=z->parent->parent->left;
if(y->color==RED){
z->parent->color=BALACK;
y->color=BALACK;
z->parent->parent->color=RED;
z=z->parent;
}else{
if(z==z->parent->left){
z=z->parentp;
_right_rotate(T,z);
}
z->parent->color=BALACK;
z->parent->parent->color=RED;
_left_rotate(T,z->parent->parent);
}
}
T->root->color=BALACK;
}
删除节点
这个有点难
总结
好了基本总结到这,我也是小白后续会陆续更新!

4475




被折叠的 条评论
为什么被折叠?



