红黑树是一个典型的key,value的结构,通过key去查找value,看上去是带颜色的二叉树。
红黑树遍历的方式是中序遍历(从中间key值的根节点开始有序查找),所以查找起来更加快速。
这里把红黑树构造理解为
红黑树 = 根节点 + 基础结构;
并且红黑树如下性质:
①根节点为黑
②叶子结点为黑(叶子结点是黑色NIL节点,也叫“哨兵”)
③红色节点不相邻
④红色的子支为黑
⑤根节点到每一个叶子的路径上黑色节点数相同(黑高)
构造如下:
typedef int KEY_TYPE;
typedef struct _rbtree_node
{
unsigned char color;
struct _rbtree_bode *left;
struct _rbtree_bode *right;
struct _rbtree_bode *parent;//有利于对红黑树旋转
KEY_TYPE key;
void *value;
}rbtree_node;//红黑树结点的定义
typedef struct _rbtree
{
rbtree_node *root;
rbtree_node *nil;//创建一个空节点,判断是否为叶子节点
};
当然红黑树作为二叉树的一种可以对其进行旋转操作:
对此,实现如图的代码
void _left_node(rbtree *T,rbtree_node *x)
{
rbtree_node *y = x->right;
x->right = y->left;
y->left = x; //第一个方向
if(y->left != T->nil){
y->left->parent=x;
}
y->parent = x->parent;
if(x->parent==T->nil){
y->root=y;
}else{
x->parent->right=y;
} //第二个方向
y->left=x;
x->parent=y; //第三个方向
}
void _right_node(rbtree *T,rbtree_node *y)
{
rbtree_node *x = y->right;
y->right = x->left;
x->left = y; //第一个方向
if(x->left != T->nil){
y->left->parent=x;
}
x->parent = y->parent;
if(y->parent==T->nil){
x->root=x;
}else{
y->parent->right=x;
} //第二个方向
x->left=y;
y->parent=x; //第三个方向
}//把全部x变成y,y变成x就成了右旋
以及实现的插入操作:
void rbtree_insert(rbtree *T,rbtree_node *z)
{
rbtree_node *x= T->root; //x相当于遍历用的i
rbtree_node *y= T->nil;
while(x != T->nil){
y = x; //这里的y就是x的父节点
if(z->key<x->key){
x = x->left;
}else if(z->key > x->key){
x = x->right;
}else{
return ;
}
} //找到对应插入z的父节点
z->parent = y;
if(y==T->nil){
T->root = z; //空的,那么z就是根节点
}else if(z->key < y->key){
y->left = z;
}else{
t->right = z;
}
z->color = RED;//默认增加红色节点,不影响黑高,只需要判断父节点是否为红
}
这里为了让新的到的红黑树仍然是红黑树,优先赋值为其赋值为红色,讨论其父节点是否是红即可。若为红色对其进行讨论:
回过头来看红黑树对子节点的颜色的处理,这实质上是为了防止同一父节点的两个分支深度相差不大。(保证每两个新节点的加入一定是在两个不一样的分支!!!<----这一点可以代入递归的思想,由红黑树最深处往根节点递归,每一个节点都满足红黑树的平衡的特性)
对红黑的树旋转则是对两个分支长度的平衡!!——>本次红黑树设计用到了fix_up函数是用于,插入一次节点必定被调用的一次处理,因为用户往往不需要对红黑树内部自动的增删改查透明,所以此函数可能被开发忽略。
void rbtree_insert_fixup(rbtree *T,rbtree_node *z){
while(z->parent->color == RED){//进入while已知:当前为RED,父节点为RED,爷爷为BLACK 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_node(T,z);
}//先旋转,再变色!
z->parent->color = BLACK;
z->parent->parent->color = RED;
}
}//????几种情况的理解
}
while(z->parent->color == RED){//进入while已知:当前为RED,父节点为RED,爷爷为BLACK
if(z->parent == z->parent->parent->right){
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;
_left_node(T,z);
}
z->parent->color = BLACK;
z->parent->parent->color = RED;
}
}//right与left交换
}
T->root->color = RED;
}