目录
一、背景
二叉搜索树(BST),在极端情况下,会退化为单支树,查找效率从 O(log2n) 退化为 O(n)。主要原因就是BST不够平衡(左右子树高度差太大)。既然如此,那么我们就需要通过一定的算法,将不平衡树改变成平衡树。因此,AVL树就诞生了。AVL要求左右子树的高度差不能超过1,是严格平衡的二叉搜索树,为了维持这种严格平衡,每次插入和删除的时候都需要旋转操作。在频繁插入、删除的场景下,AVL的性能会大打折扣。红黑树通过牺牲严格的平衡性质,换取减少每次插入和删除的旋转操作。
二、红黑树作用和用途
1、用法
(1)key, value ---> 主要用于查找
(2)中序遍历是顺序的 --> 主要用于查找范围
2、用途
(1)map
(2)nginx timer定时器
(3)定时器
(4)cfs 进程管理
(5)内存管理(首地址做key,内存长度做value)
三、红黑树的性质
- 每个节点是红的或者黑的
- 根节点是黑的
- 每个叶子节点是黑的
- 如果一个节点是红的,则它的两个儿子都是黑的
- 对每个节点,从该节点到其子孙节点的所有路径上的包含相同数目的黑节点
四、代码实现
1、定义
typedef int KEY_TYPE;
#define RBTREE_ENTRY(name, type) \
struct name { \
unsigned char color; \
struct type *left; \
struct type *right; \
struct type *parent; \
}
//红黑树节点,先定义一个节点的性质,再定义头尾指针
typedef struct _rbtree_node
{
#if 0
unsigned char color; //颜色
struct _rbtree_node *left; //左子树
struct _rbtree_node *right; //右子树
struct _rbtree_node *parent; //父节点,旋转用
#else
RBTREE_ENTRY(, _rbtree_node) node; //type类型可变
#endif
/*只要符合以上4条性质,就是红黑树*/
KEY_TYPE key; //用于对比,通过key值查找
void *value;
}rbtree_node;
typedef struct _rbtree
{
rbtree_node *root; //根节点
rbtree_node *nil; //通用节点、空节点,用于判断叶子节点(所有叶子节点都指向nil,若不指向nil则不是叶子节点)。【不是NULL】
}rbtree;
/********以上是红黑树的定义, 但有个问题:
* 4条性质被写死了,最好的是把红黑树的性质封装成模板RBTREE_ENTRY,key、value做业务使用
* ***********/
2、旋转
当红黑树性质被破坏时,触发旋转,进行调整,即2个原语操作:左旋和右旋。
旋转的意义是:当有新节点插入、删除时,可能导致节点不符合红黑树的性质,为了平衡,所以要旋转。类似魔方打乱了,复原时候需要公式,左旋、右旋就是基本公式。
注意:左旋、右旋最大次数就是树的高度,左旋、右旋都不需要改变颜色。
//左旋
void rbtree_left_rotate(rbtree *T, rbtree_node *x) {
/*要修改的指针方向:
1.x右子树改为指向b;
2.y的左子树改为指向x;
3.x的父节点改为指向y。
每一个都是双向的,这里要改变6个指针。
*/
rbtree_node *y = x->right; // x --> y , y --> x, right --> left, left --> right
//1. x右子树改为指向b
x->right = y->left; //1 1 x右子树改为指向b
if (y->left != T->nil) { //1 2 //判断y的左子树是不是叶子节点,如果不是就要改
y->left->parent = x; //y的左子树改为指向x
}
//2.y的左子树改为指向x
y->parent = x->parent; //1 3
if (x->parent == T->nil) { //1 4 //判断x是不是根节点。x的parent为空,即x是根节点
T->root = y; //把根节点变为y
} else if (x == x->parent->left) { //x不是根节点,是根节点的左子树
x->parent->left = y; //把根节点的左子树变为y
} else { //x不是根节点,是根节点的右子树
x->parent->right = y; //把根节点的右子树变为y
}
//3.x的父节点改为指向y
y->left = x; //1 5
x->parent = y; //1 6
}
右旋:把左旋反过来即可。
//右旋
void rbtree_right_rotate(rbtree *T, rbtree_node *y) {
/*
把左旋的x y互换,left right互换
*/
rbtree_node *x = y->left;
//1.
y->left = x->right;
if (x->right != T->nil) {
x->right->parent = y;
}
//2.
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;
}
//3.
x->right = y;
y->parent = x;
}
3、插入
void rbtree_insert_fixup(rbtree *T, rbtree_node *z) { //插入的z节点是红色的
while (z->parent->color == RED) { //z ---> RED
/*
z的父节点是红色
z的祖父节点是黑色
z的叔父节点 不确定
*/
if (z->parent == z->parent->parent->left) { //z的父节点是祖父节点的左子树
rbtree_node *y = z->parent->parent->right; //祖父节点的右子树,即叔父节点,uncle
if (y->color == RED) { //叔父节点 红色
z->parent->color = BLACK;
y->color = BLACK;
z->parent->parent->color = RED;
z = z->parent->parent; //z --> RED 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);
}
}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; //z --> RED
} else {
if (z == z->parent->left) {
z = z->parent;
rbtree_right_rotate(T, z);
}
z->parent->color = BLACK;
z->parent->parent->color = RED;
rbtree_left_rotate(T, z->parent->parent);
}
}
}
T->root->color = BLACK;
}
//插入
//前提:红黑树在插入任何节点之前,就已经是红黑树
void rbtree_insert(rbtree *T, rbtree_node *z) {
rbtree_node *y = T->nil;
rbtree_node *x = T->root; //根节点
while (x != T->nil) { //循环,x!=叶子节点
y = x; //y指向x的parent
if (z->key < x->key) { //比x小,插左子树
x = x->left;
} else if (z->key > x->key) { //比x大,插右子树
x = x->right;
} else { //Exist 已经存在
return ;
}
}
//x = T->nil; 上面这个循环执行完之后,x插到叶子节点最底,指向的是空
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); //调整
}
4、删除
void rbtree_delete_fixup(rbtree *T, rbtree_node *x) {
while ((x != T->root) && (x->color == BLACK)) {
if (x == x->parent->left) {
rbtree_node *w= x->parent->right;
if (w->color == RED) {
w->color = BLACK;
x->parent->color = RED;
rbtree_left_rotate(T, x->parent);
w = x->parent->right;
}
if ((w->left->color == BLACK) && (w->right->color == BLACK)) {
w->color = RED;
x = x->parent;
} else {
if (w->right->color == BLACK) {
w->left->color = BLACK;
w->color = RED;
rbtree_right_rotate(T, w);
w = x->parent->right;
}
w->color = x->parent->color;
x->parent->color = BLACK;
w->right->color = BLACK;
rbtree_left_rotate(T, x->parent);
x = T->root;
}
} else {
rbtree_node *w = x->parent->left;
if (w->color == RED) {
w->color = BLACK;
x->parent->color = RED;
rbtree_right_rotate(T, x->parent);
w = x->parent->left;
}
if ((w->left->color == BLACK) && (w->right->color == BLACK)) {
w->color = RED;
x = x->parent;
} else {
if (w->left->color == BLACK) {
w->right->color = BLACK;
w->color = RED;
rbtree_left_rotate(T, w);
w = x->parent->left;
}
w->color = x->parent->color;
x->parent->color = BLACK;
w->left->color = BLACK;
rbtree_right_rotate(T, x->parent);
x = T->root;
}
}
}
x->color = BLACK;
}
//删除
rbtree_node *rbtree_delete(rbtree *T, rbtree_node *z) {
rbtree_node *y = T->nil;
rbtree_node *x = T->nil;
if ((z->left == T->nil) || (z->right == T->nil)) {
y = z;
} else {
y = rbtree_successor(T, z);
}
if (y->left != T->nil) {
x = y->left;
} else if (y->right != T->nil) {
x = y->right;
}
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;
}
if (y != z) {
z->key = y->key;
z->value = y->value;
}
if (y->color == BLACK) {
rbtree_delete_fixup(T, x);
}
return y;
}
5、遍历和变色
rbtree_node *rbtree_search(rbtree *T, KEY_TYPE key) {
rbtree_node *node = T->root;
while (node != T->nil) {
if (key < node->key) {
node = node->left;
} else if (key > node->key) {
node = node->right;
} else {
return node;
}
}
return T->nil;
}
void rbtree_traversal(rbtree *T, rbtree_node *node) {
if (node != T->nil) {
rbtree_traversal(T, node->left);
printf("key:%d, color:%d\n", node->key, node->color);
rbtree_traversal(T, node->right);
}
}
https://course.0voice.com/v1/course/intro?courseId=5&agentId=0