红黑树是许多“平衡”搜索树中的一种,可以保证在最坏情况下基本动态集合操作的时间复杂度为O(lgn)。
用途
- stl map 红黑树封装
- nginx
- 定时器
- cfs(进程调度,用红黑树存储进程的集合,将调度的时间作为key值)
- 内存管理(将内存块用红黑树存储,开始位置作为key,指针指向内存块)
性质
- 每个节点是红的或者黑的
- 根节点是黑的
- 每个叶子节点是黑的
- 如果一个节点是红的,他的两个孩子都是黑的
- 对每个节点,从该节点到其子孙节点的所有路径上包含相同数目的黑节点
定义
树中每个节点包含5个属性:color、key、left、right、p。如果一个节点没有子节点或父节点,则该节点相应指针属性的值为NIL。可以将NIL视为指向二叉搜索树的叶节点(外部节点)的指针,把带关键字的节点视为树的内部节点。
定义一个通用的节点,将每个叶子节点指向此节点来判断是否为叶子节点。
typedef int KEY_TYPE;
typedef struct _rbtree_node {
unsigned char color;
struct _rbtree_node *right;
struct _rbtree_node *left;
struct _rbtree_node *parent;
KEY_TYPE key;
void *value;
} rbtree_node;
typedef struct _rbtree {
rbtree_node *root;
rbtree_node *nil;
} rbtree;
旋转
左旋
- x的右子树指向b;
- b的parrent指向x;
- y的parrent指向x的parrent(x的parrent分三种情况判断)
- y的左子树指向x;
//左旋
void rbtree_left_rotate(rbtree *T, rbtree_node *x) {
rbtree_node *y = x->right; // x --> y , y --> x, right --> left, left --> right
x->right = y->left; //1 1
if (y->left != T->nil) { //1 2
y->left->parent = x;
}
y->parent = x->parent; //1 3
if (x->parent == T->nil) { //1 4
T->root = y;
} else if (x == x->parent->left) {
x->parent->left = y;
} else {
x->parent->right = y;
}
y->left = x; //1 5
x->parent = y; //1 6
}
右旋
和左旋相反
void rbtree_right_rotate(rbtree *T, rbtree_node *y) {
rbtree_node *x = y->left;
y->left = x->right;
if (x->right != T->nil) {
x->right->parent = y;
}
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;
}
x->right = y;
y->parent = x;
}
添加
新节点添加到最底层的非叶子节点。
前提:
- 父节点是祖父的左子树;
- 当前已满足红黑树性质;
- 插入红色节点;
父节点是红色:
- 叔父节点是红色;
- 叔父节点是黑色,当前节点父节点左子树;
- 叔父节点是黑色,当前节点父节点右子树;
void rbtree_insert_fixup(rbtree *T, rbtree_node *z) {
while (z->parent->color == RED) { //z ---> 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; //z --> RED
} 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) {
y = x;
if (z->key < x->key) {
x = x->left;
} else if (z->key > x->key) {
x = x->right;
} else { //Exist
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);
}