一. 红黑树的定义
红黑树(Red Black Tree)是一种自平衡二叉查找树,红黑树插入,删除,查找都是O(logn)的时间复杂度。
二. 红黑树的性质
每个节点或红或黑
根结点为黑
每个叶子节点为黑
若一个节点为红,则它的孩子必须为黑
对每个节点,从该节点到其他子孙节点的所有路径上包含相同数目的黑色节点
第五条性质尤为重要,第五条性质表明红黑树不同于AVL树。红黑树平衡的是黑高,而AVL树平衡的是子树高度。
三. 红黑树的用途
map, set底层采用红黑树进行存储
定时器
Linux进程调度(CFS(Completely FairScheduler))
Epoll的实现,内核会在内存中开辟一个空间存放epoll的红黑树,并将每个epollfd加入树中进行管理
四. 红黑树的插入
- 红黑树节点旋转
红黑树在插入和删除过程中,由于破坏黑高,需要进行调整,而调整的过程中就会涉及到节点旋转的操作。可以说节点旋转是红黑树中非常重要的操作之一。

// 左旋操作
void RBtree::leftRotate(RBtree_node *x)
{
RBtree_node *y = x->right;
x->right = y->left;
if (y->left != nil)
{
y->left->parent = x;
}
y->parent = x->parent;
if (x->parent == nil)
{
root = y;
}
else if (x->parent->left == x)
{
x->parent->left = y;
}
else
{
x->parent->right = y;
}
y->left = x;
x->parent = y;
}
// 右旋操作
void RBtree::rightRotate(RBtree_node *y)
{
RBtree_node *x = y->left;
y->left = x->right;
if (x->right != nil)
{
x->right->parent = y;
}
x->parent = y->parent;
if (y->parent == nil)
{
root = x;
}
else if (y->parent->left == y)
{
y->parent->left = x;
}
else
{
y->parent->right = x;
}
x->right = y;
y->parent = x;
}
- 红黑树插入节点
红黑树插入节点类似于二叉搜索树的插入,都是要先在树上寻找到合适的插入位置,再进行节点插入(插入叶子节点),只不过红黑树在插入结束之后要进行节点调整。所以在红黑树中插入节点有以下几个步骤:1. 寻找插入位置
2. 创建新节点
3. 插入,调整
// 节点插入
void RBtree::insert(KEY_TYPE key, VALUE_TYPE value)
{
RBtree_node *pre = nil;
RBtree_node *cur = root;
// 寻找插入位置
while (cur != nil)
{
pre = cur;
if (key < cur->key)
{
cur = cur->left;
}
else if (key > cur->key)
{
cur = cur->right;
}
else
{
return;
}
}
// 创建新节点
RBtree_node *node = new RBtree_node(RED);
node->key = key;
node->value = value;
node->left = nil;
node->right = nil;
node->parent = pre;
// 新节点插入红黑树
if (pre == nil)
{
root = node;
}
else
{
if (key < pre->key)
{
pre->left = node;
}
else
{
pre->right = node;
}
}
// 插入调整
insert_fixup(node);
}
- 红黑树插入调整
若插入节点时,将插入节点颜色设置为黑色,插入红黑树中必定会将黑高平衡破坏,这样每次插入节点都会带来红黑树的调整。
若插入节点时,将插入节点颜色设置为红色,插入红黑树一定不会破坏黑高,但是会破坏性质4, 此时若插入节点父节点为红色节点,则需要进行调整。现在以插入节点的父节点为祖父节点的左孩子为例:
情况一:叔父节点为红色

此时将父亲节点染为黑色,叔父节点染为黑色,将祖父节点染为红色。之后从祖父节点开始继续向上迭代检查。
情况2:叔父节点为黑色,插入节点为父亲节点右孩子

此时将以插入节点父节点为轴心进行左旋,此时转化为情况3
情况3. 叔父节点为黑色,插入节点为父亲节点左孩子。

此时将父节点染为黑色,将祖父节点染为红色,以祖父节点为轴型进行右旋。
// 插入修复
void RBtree::insert_fixup(RBtree_node *x)
{
// 迭代检查父节点是否为红色,若为红色继续调整
while (x->parent->color == RED)
{
// 当父节点为祖父节点左孩子
if (x->parent == x->parent->parent->left)
{
// 叔父节点
RBtree_node *y = x->parent->parent->right;
// 情况1
if (y->color == RED)
{
x->parent->color = BLACK;
y->color = BLACK;
x->parent->parent->color = RED;
x = x->parent->parent;
}
else
{
// 情况2
if (x == x->parent->right)
{
x = x->parent;
leftRotate(x);
}
// 情况3
x->parent->color = BLACK;
x->parent->parent->color = RED;
rightRotate(x->parent->parent);
}
}
else
{
RBtree_node *y = x->parent->parent->left;
if (y->color == RED)
{
x->parent->color = BLACK;
y->color = BLACK;
x->parent->parent->color = RED;
x = x->parent->parent;
}
else
{
if (x == x->parent->left)
{
x = x->parent;
rightRotate(x);
}
x->parent->color = BLACK;
x->parent->parent->color = RED;
leftRotate(x->parent->parent);
}
}
}
// 保证根节点一直为黑色
root->color = BLACK;
}
五.红黑树的删除
- 寻找一个子树上的最小节点和最大节点
RBtree_node *RBtree::mini_node(RBtree_node *x)
{
while (x->left != nil)
{
x = x->left;
}
return x;
}
RBtree_node *RBtree::max_node(RBtree_node *x)
{
while (x->right != nil)
{
x = x->right;
}
return x;
}
- 寻找一个节点的后继节点
当寻找一个节点的后继节点时,存在两种情况:
情况1:该节点存在右子树,此时后继节点为右子树的最小值节点
情况2:该节点不存在右子树,此时后继节点为父节点不断迭代向上搜索,直到当前节点为父节点的左孩子节点,此时父节点为后继节点,例如13节点的后继节点为15

RBtree_node *RBtree::successor(RBtree_node *node)
{
// 情况1
if (node->right != nil)
{
return mini_node(node->right);
}
// 情况2
else
{
RBtree_node *pre = node->parent;
RBtree_node *cur = node;
while (pre != nil && cur == pre->right)
{
cur = pre;
pre = pre->parent;
}
return pre;
}
}
- 红黑树删除节点
红黑树删除时分为如下几种情况:
- 该删除节点不存在左右子树

若遇到该情况,则直接删除节点
- 删除节点存在右左子树或右子树

若遇到该情况,将该节点直接删除并且将左子树或右子树代替被删除节点位置。
- 删除节点存在左子树且存在右子树

若遇到该情况,则寻找插入节点z的直接后继节点y,将y节点替换z节点值,最后删除y节点,y的右孩子连接y的父节点。
// 删除节点
void RBtree::erase(KEY_TYPE key)
{
// y节点的孩子节点
RBtree_node *x = nil;
// 真正删除节点
RBtree_node *y = nil;
// 被覆盖节点
RBtree_node *z = search_node(key);
if (z == nil)
{
return;
}
// 情况1, 2
if (z->left == nil || z->right == nil)
{
y = z;
}
else
{
// 情况3
y = successor(z);
}
// x为y的左或右子树
if (y->left != nil)
{
x = y->left;
}
if (y->right != nil)
{
x = y->right;
}
// 将x代替y的位置
x->parent = y->parent;
if (y->parent == nil)
{
root = x;
}
else if (y == y->parent->left)
{
y->parent->left = x;
}
else
{
y->parent->right = x;
}
// 将y值覆盖z值
if (y != z)
{
z->key = y->key;
z->value = y->value;
}
// 若删除节点y为黑色节点,则破坏黑高,进行调整
if (y->color == BLACK)
{
erase_fixup(x);
}
}
- 红黑树删除节点调整
接上文,已知条件,y节点为黑色
调整节点为y节点的孩子节点x,若x节点颜色为红色,则直接将x节点染为黑色即可,此时不会破坏黑高。
调整节点为y节点的孩子节点x,若x节点颜色为黑色,此时破坏黑高,需要进行调整。
此时分为四种情况(以x节点为y节点左孩子节点为例)
情况1. 兄弟节点为红色:

解决方法:将兄弟节点染为黑色,将父亲节点染为红色,进行左旋。
情况2:兄弟节点为黑色,且兄弟节点的左孩子右孩子节点都为黑色节点

解决方法:将兄弟节点染为红色
情况3. 兄弟节点为黑色,兄弟节点的左孩子为红色,右孩子为黑色

解决方法:此时将兄弟节点左孩子染为黑色,兄弟节点染为黑色,以兄弟节点为轴心进行右旋,转换为情况4
情况4.兄弟节点右孩子为红色

解决方法:将x父节点右孩子染为父节点颜色,x父节点染为黑色,兄弟节点右孩子染为黑色,以x父节点为轴心进行左旋,左旋结束之后结束循环。
void RBtree::erase_fixup(RBtree_node *x)
{
while (x != root && x->color == BLACK)
{
if (x == x->parent->left)
{
RBtree_node *y = x->parent->right;
// 情况1
if (y->color == RED)
{
y->color = BLACK;
x->parent->color = RED;
leftRotate(x->parent);
y = x->parent->right;
}
// 情况2
if (y->left->color == BLACK && y->right->color == BLACK)
{
y->color = RED;
x = x->parent;
}
else
{
// 情况3
if (y->right->color == BLACK)
{
y->color = RED;
y->left->color = BLACK;
rightRotate(y);
y = x->parent->right;
}
// 情况4
y->color = x->parent->color;
x->parent->color = BLACK;
y->right->color = BLACK;
leftRotate(x->parent);
x = root;
}
}
else
{
RBtree_node *y = x->parent->left;
if (y->color == RED)
{
y->color = BLACK;
x->parent->color = RED;
rightRotate(x->parent);
y = x->parent->left;
}
if (y->left->color == BLACK && y->right->color == BLACK)
{
y->color = RED;
x = x->parent;
}
else
{
if (y->left->color == BLACK)
{
y->color = RED;
y->right->color = BLACK;
leftRotate(y);
y = x->parent->left;
}
y->color = x->parent->color;
x->parent->color = BLACK;
y->left->color = BLACK;
rightRotate(x->parent);
x = root;
}
}
}
x->color = BLACK;
}
六. 完整代码
#ifndef RBTREE_H
#define RBTREE_H
typedef enum _COLOR
{
BLACK = 0,
RED = 1
} COLOR;
using KEY_TYPE = int;
using VALUE_TYPE = int;
class RBtree_node
{
public:
KEY_TYPE key;
VALUE_TYPE value;
COLOR color;
class RBtree_node *left;
class RBtree_node *right;
class RBtree_node *parent;
RBtree_node(COLOR c)
: color(c),
key(-1),
value(-1),
parent(nullptr),
left(nullptr),
right(nullptr)
{
}
};
class RBtree
{
public:
RBtree()
{
nil = new RBtree_node(BLACK);
root = nil;
}
// 插入
void insert(KEY_TYPE key, VALUE_TYPE value);
// 删除
void erase(KEY_TYPE key);
// 寻找某个Key值是否存在
bool find(KEY_TYPE key);
// 层序遍历打印红黑树
void print_level();
// 中序遍历红黑树
void print_middle();
private:
// 左旋
void leftRotate(RBtree_node *x);
// 右旋
void rightRotate(RBtree_node *y);
// 插入修复
void insert_fixup(RBtree_node *x);
// 删除修复
void erase_fixup(RBtree_node *x);
// 查询某个key节点
RBtree_node *search_node(KEY_TYPE key);
// 寻找某个节点后继节点
RBtree_node *successor(RBtree_node *node);
// 寻找某颗子树上最小节点
RBtree_node *mini_node(RBtree_node *x);
// 寻找某颗子树上最大节点
RBtree_node *max_node(RBtree_node *x);
private:
RBtree_node *root;
RBtree_node *nil;
};
#endif // RBTREE_H
#include "rbtree.h"
#include <iostream>
#include <queue>
#include <stack>
using namespace std;
void RBtree::insert(KEY_TYPE key, VALUE_TYPE value)
{
RBtree_node *pre = nil;
RBtree_node *cur = root;
while (cur != nil)
{
pre = cur;
if (key < cur->key)
{
cur = cur->left;
}
else if (key > cur->key)
{
cur = cur->right;
}
else
{
return;
}
}
RBtree_node *node = new RBtree_node(RED);
node->key = key;
node->value = value;
node->left = nil;
node->right = nil;
node->parent = pre;
if (pre == nil)
{
root = node;
}
else
{
if (key < pre->key)
{
pre->left = node;
}
else
{
pre->right = node;
}
}
insert_fixup(node);
}
void RBtree::erase(KEY_TYPE key)
{
RBtree_node *x = nil;
RBtree_node *y = nil;
RBtree_node *z = search_node(key);
if (z == nil)
{
return;
}
if (z->left == nil || z->right == nil)
{
y = z;
}
else
{
y = successor(z);
}
if (y->left != nil)
{
x = y->left;
}
if (y->right != nil)
{
x = y->right;
}
x->parent = y->parent;
if (y->parent == nil)
{
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)
{
erase_fixup(x);
}
}
bool RBtree::find(KEY_TYPE key)
{
RBtree_node *node = search_node(key);
if (node != nil)
{
return true;
}
else
{
return false;
}
}
void RBtree::print_level()
{
if (root == nil)
{
return;
}
queue<RBtree_node *> q;
RBtree_node *cur_end = root;
RBtree_node *next_end = nullptr;
q.push(root);
int level = 1;
while (!q.empty())
{
RBtree_node *node = q.front();
q.pop();
if (node != nil)
{
cout << "key:" << node->key << " value:" << node->value
<< " color:" << (node->color == RED ? "RED" : "BLACK")
<< " level:" << level << endl;
}
else
{
cout << "nil node"
<< " level:" << level << endl;
}
if (node->left)
{
q.push(node->left);
next_end = node->left;
}
if (node->right)
{
q.push(node->right);
next_end = node->right;
}
if (node == cur_end)
{
if (cur_end != next_end)
{
level++;
}
cur_end = next_end;
}
}
}
void RBtree::print_middle()
{
stack<RBtree_node *> s;
RBtree_node *cur = root;
while (cur != nil || !s.empty())
{
if (cur != nil)
{
s.push(cur);
cur = cur->left;
}
else
{
RBtree_node *node = s.top();
s.pop();
cout << "key = " << node->key << "value = " << node->value << endl;
cur = node->right;
}
}
}
void RBtree::leftRotate(RBtree_node *x)
{
RBtree_node *y = x->right;
x->right = y->left;
if (y->left != nil)
{
y->left->parent = x;
}
y->parent = x->parent;
if (x->parent == nil)
{
root = y;
}
else if (x->parent->left == x)
{
x->parent->left = y;
}
else
{
x->parent->right = y;
}
y->left = x;
x->parent = y;
}
void RBtree::rightRotate(RBtree_node *y)
{
RBtree_node *x = y->left;
y->left = x->right;
if (x->right != nil)
{
x->right->parent = y;
}
x->parent = y->parent;
if (y->parent == nil)
{
root = x;
}
else if (y->parent->left == y)
{
y->parent->left = x;
}
else
{
y->parent->right = x;
}
x->right = y;
y->parent = x;
}
void RBtree::insert_fixup(RBtree_node *x)
{
while (x->parent->color == RED)
{
if (x->parent == x->parent->parent->left)
{
RBtree_node *y = x->parent->parent->right;
if (y->color == RED)
{
x->parent->color = BLACK;
y->color = BLACK;
x->parent->parent->color = RED;
x = x->parent->parent;
}
else
{
if (x == x->parent->right)
{
x = x->parent;
leftRotate(x);
}
x->parent->color = BLACK;
x->parent->parent->color = RED;
rightRotate(x->parent->parent);
}
}
else
{
RBtree_node *y = x->parent->parent->left;
if (y->color == RED)
{
x->parent->color = BLACK;
y->color = BLACK;
x->parent->parent->color = RED;
x = x->parent->parent;
}
else
{
if (x == x->parent->left)
{
x = x->parent;
rightRotate(x);
}
x->parent->color = BLACK;
x->parent->parent->color = RED;
leftRotate(x->parent->parent);
}
}
}
root->color = BLACK;
}
void RBtree::erase_fixup(RBtree_node *x)
{
while (x != root && x->color == BLACK)
{
if (x == x->parent->left)
{
RBtree_node *y = x->parent->right;
if (y->color == RED)
{
y->color = BLACK;
x->parent->color = RED;
leftRotate(x->parent);
y = x->parent->right;
}
if (y->left->color == BLACK && y->right->color == BLACK)
{
y->color = RED;
x = x->parent;
}
else
{
if (y->right->color == BLACK)
{
y->color = RED;
y->left->color = BLACK;
rightRotate(y);
y = x->parent->right;
}
y->color = x->parent->color;
x->parent->color = BLACK;
y->right->color = BLACK;
leftRotate(x->parent);
x = root;
}
}
else
{
RBtree_node *y = x->parent->left;
if (y->color == RED)
{
y->color = BLACK;
x->parent->color = RED;
rightRotate(x->parent);
y = x->parent->left;
}
if (y->left->color == BLACK && y->right->color == BLACK)
{
y->color = RED;
x = x->parent;
}
else
{
if (y->left->color == BLACK)
{
y->color = RED;
y->right->color = BLACK;
leftRotate(y);
y = x->parent->left;
}
y->color = x->parent->color;
x->parent->color = BLACK;
y->left->color = BLACK;
rightRotate(x->parent);
x = root;
}
}
}
x->color = BLACK;
}
RBtree_node *RBtree::search_node(KEY_TYPE key)
{
RBtree_node *node = root;
while (node != nil)
{
if (key < node->key)
{
node = node->left;
}
else if (key > node->key)
{
node = node->right;
}
else
{
return node;
}
}
return nil;
}
RBtree_node *RBtree::successor(RBtree_node *node)
{
if (node->right != nil)
{
return mini_node(node->right);
}
else
{
RBtree_node *pre = node->parent;
RBtree_node *cur = node;
while (pre != nil && cur == pre->right)
{
cur = pre;
pre = pre->parent;
}
return pre;
}
}
RBtree_node *RBtree::mini_node(RBtree_node *x)
{
while (x->left != nil)
{
x = x->left;
}
return x;
}
RBtree_node *RBtree::max_node(RBtree_node *x)
{
while (x->right != nil)
{
x = x->right;
}
return x;
}
测试代码:
#include "rbtree.h"
#include <iostream>
int main()
{
RBtree tree;
for (int i = 0; i < 10; i++)
{
tree.insert(i, i);
}
tree.print_level();
std::cout << "after erase" << std::endl;
tree.erase(3);
tree.print_level();
tree.print_middle();
return 0;
}