昨天下班在地铁上居然听到有人在讨论红黑树,这块虽然一直在用,但早已忘了具体的实现细节,利用周天上午的时间,学习红黑树的知识。
以下红黑树的基本概念来自维基百科红黑树,详细介绍请阅读该文章。
另一篇非常不错的文章:红黑树的变色与旋转
可以拿来直接工程中使用的代码:libtree-github
红黑树(英语:Red–black tree)是一种自平衡二叉查找树,是在计算机科学中用到的一种数据结构,典型的用途是实现关联数组。
红黑树是每个节点都带有颜色属性的二叉查找树,颜色为红色或黑色。在二叉查找树强制一般要求以外,对于任何有效的红黑树我们增加了如下的额外要求:
性质
1.节点是红色或黑色。
2.根是黑色。
3.所有叶子都是黑色(叶子是NIL节点)。
4.每个红色节点必须有两个黑色的子节点。(从每个叶子到根的所有路径上不能有两个连续的红色节点。)
5.从任一节点到其每个叶子的所有简单路径都包含相同数目的黑色节点。
下面是一个具体的红黑树的图例:
这些约束确保了红黑树的关键特性:从根到叶子的最长的可能路径不多于最短的可能路径的两倍长。结果是这个树大致上是平衡的。因为操作比如插入、删除和查找某个值的最坏情况时间都要求与树的高度成比例,这个在高度上的理论上限允许红黑树在最坏情况下都是高效的,而不同于普通的二叉查找树。
要知道为什么这些性质确保了这个结果,注意到性质4导致了路径不能有两个毗连的红色节点就足够了。最短的可能路径都是黑色节点,最长的可能路径有交替的红色和黑色节点。因为根据性质5所有最长的路径都有相同数目的黑色节点,这就表明了没有路径能多于任何其他路径的两倍长。
在很多树数据结构的表示中,一个节点有可能只有一个子节点,而叶子节点包含数据。用这种范例表示红黑树是可能的,但是这会改变一些性质并使算法复杂。为此,本文中我们使用"nil叶子"或"空(null)叶子",如上图所示,它不包含数据而只充当树在此结束的指示。这些节点在绘图中经常被省略,导致了这些树好像同上述原则相矛盾,而实际上不是这样。与此有关的结论是所有节点都有两个子节点,尽管其中的一个或两个可能是空叶子。
红黑树原版无注释C++实现:
#define BLACK 1
#define RED 0
#include <iostream>
using namespace std;
class bst {
private:
struct Node {
int value;
bool color;
Node *leftTree, *rightTree, *parent;
Node() : value(0), color(RED), leftTree(NULL), rightTree(NULL), parent(NULL) { }
Node* grandparent() {
if(parent == NULL){
return NULL;
}
return parent->parent;
}
Node* uncle() {
if(grandparent() == NULL) {
return NULL;
}
if(parent == grandparent()->rightTree)
return grandparent()->leftTree;
else
return grandparent()->rightTree;
}
Node* sibling() {
if(parent->leftTree == this)
return parent->rightTree;
else
return parent->leftTree;
}
};
void rotate_right(Node *p){
Node *gp = p->grandparent();
Node *fa = p->parent;
Node *y = p->rightTree;
fa->leftTree = y;
if(y != NIL)
y->parent = fa;
p->rightTree = fa;
fa->parent = p;
if(root == fa)
root = p;
p->parent = gp;
if(gp != NULL){
if(gp->leftTree == fa)
gp->leftTree = p;
else
gp->rightTree = p;
}
}
void rotate_left(Node *p){
if(p->parent == NULL){
root = p;
return;
}
Node *gp = p->grandparent();
Node *fa = p->parent;
Node *y = p->leftTree;
fa->rightTree = y;
if(y != NIL)
y->parent = fa;
p->leftTree = fa;
fa->parent = p;
if(root == fa)
root = p;
p->parent = gp;
if(gp != NULL){
if(gp->leftTree == fa)
gp->leftTree = p;
else
gp->rightTree = p;
}
}
void inorder(Node *p){
if(p == NIL)
return;
if(p->leftTree)
inorder(p->leftTree);
cout << p->value << " ";
if(p->rightTree)
inorder(p->rightTree);
}
string outputColor (bool color) {
return color ? "BLACK" : "RED";
}
Node* getSmallestChild(Node *p){
if(p->leftTree == NIL)
return p;
return getSmallestChild(p->leftTree);
}
bool delete_child(Node *p, int data){
if(p->value > data){
if(p->leftTree == NIL){
return false;
}
return delete_child(p->leftTree, data);
} else if(p->value < data){
if(p->rightTree == NIL){
return false;
}
return delete_child(p->rightTree, data);
} else if(p->value == data){
if(p->rightTree == NIL){
delete_one_child (p);
return true;
}
Node *smallest = getSmallestChild(p->rightTree);
swap(p->value, smallest->value);
delete_one_child (smallest);
return true;
}else{
return false;
}
}
void delete_one_child(Node *p){
Node *child = p->leftTree == NIL ? p->rightTree : p->leftTree;
if(p->parent == NULL && p->leftTree == NIL && p->rightTree == NIL){
p = NULL;
root = p;
return;
}
if(p->parent == NULL){
delete p;
child->parent = NULL;
root = child;
root->color = BLACK;
return;
}
if(p->parent->leftTree == p){
p->parent->leftTree = child;
} else {
p->parent->rightTree = child;
}
child->parent = p->parent;
if(p->color == BLACK){
if(child->color == RED){
child->color = BLACK;
} else
delete_case (child);
}
delete p;
}
void delete_case(Node *p){
if(p->parent == NULL){
p->color = BLACK;
return;
}
if(p->sibling()->color == RED) {
p->parent->color = RED;
p->sibling()->color = BLACK;
if(p == p->parent->leftTree)
//rotate_left(p->sibling());
rotate_left(p->parent);
else
//rotate_right(p->sibling());
rotate_right(p->parent);
}
if(p->parent->color == BLACK && p->sibling()->color == BLACK
&& p->sibling()->leftTree->color == BLACK && p->sibling()->rightTree->color == BLACK) {
p->sibling()->color = RED;
delete_case(p->parent);
} else if(p->parent->color == RED && p->sibling()->color == BLACK
&& p->sibling()->leftTree->color == BLACK && p->sibling()->rightTree->color == BLACK) {
p->sibling()->color = RED;
p->parent->color = BLACK;
} else {
if(p->sibling()->color == BLACK) {
if(p == p->parent->leftTree && p->sibling()->leftTree->color == RED
&& p->sibling()->rightTree->color == BLACK) {
p->sibling()->color = RED;
p->sibling()->leftTree->color = BLACK;
rotate_right(p->sibling()->leftTree);
} else if(p == p->parent->rightTree && p->sibling()->leftTree->color == BLACK
&& p->sibling()->rightTree->color == RED) {
p->sibling()->color = RED;
p->sibling()->rightTree->color = BLACK;
rotate_left(p->sibling()->rightTree);
}
}
p->sibling()->color = p->parent->color;
p->parent->color = BLACK;
if(p == p->parent->leftTree){
p->sibling()->rightTree->color = BLACK;
rotate_left(p->sibling());
} else {
p->sibling()->leftTree->color = BLACK;
rotate_right(p->sibling());
}
}
}
void insert(Node *p, int data){
if(p->value >= data){
if(p->leftTree != NIL)
insert(p->leftTree, data);
else {
Node *tmp = new Node();
tmp->value = data;
tmp->leftTree = tmp->rightTree = NIL;
tmp->parent = p;
p->leftTree = tmp;
insert_case (tmp);
}
} else {
if(p->rightTree != NIL)
insert(p->rightTree, data);
else {
Node *tmp = new Node();
tmp->value = data;
tmp->leftTree = tmp->rightTree = NIL;
tmp->parent = p;
p->rightTree = tmp;
insert_case (tmp);
}
}
}
void insert_case(Node *p){
if(p->parent == NULL){
root = p;
p->color = BLACK;
return;
}
if(p->parent->color == RED){
if(p->uncle()->color == RED) {
p->parent->color = p->uncle()->color = BLACK;
p->grandparent()->color = RED;
insert_case(p->grandparent());
} else {
if(p->parent->rightTree == p && p->grandparent()->leftTree == p->parent) {
rotate_left(p);
p->color = BLACK;
p->leftTree->color = p->rightTree->color = RED;
} else if(p->parent->leftTree == p && p->grandparent()->rightTree == p->parent) {
rotate_right(p);
p->color = BLACK;
p->leftTree->color = p->rightTree->color = RED;
} else if(p->parent->leftTree == p && p->grandparent()->leftTree == p->parent) {
p->parent->color = BLACK;
p->grandparent()->color = RED;
rotate_right(p->parent);
} else if(p->parent->rightTree == p && p->grandparent()->rightTree == p->parent) {
p->parent->color = BLACK;
p->grandparent()->color = RED;
rotate_left(p->parent);
}
}
}
}
void DeleteTree(Node *p){
if(!p || p == NIL){
return;
}
DeleteTree(p->leftTree);
DeleteTree(p->rightTree);
delete p;
}
public:
bst() {
NIL = new Node();
NIL->color = BLACK;
root = NULL;
}
~bst() {
if (root)
DeleteTree (root);
delete NIL;
}
void inorder() {
if(root == NULL)
return;
inorder(root);
cout << endl;
}
void insert (int x) {
if(root == NULL){
root = new Node();
root->color = BLACK;
root->leftTree = root->rightTree = NIL;
root->value = x;
} else {
insert(root, x);
}
}
bool delete_value (int data) {
return delete_child(root, data);
}
private:
Node *root, *NIL;
};
int main()
{
bst rbt;
int i = 0;
/*插入0到10*/
for(;i <= 10;i++){
rbt.insert(i);
}
/*验证插入结果*/
rbt.inorder();
/*删除10*/
rbt.delete_value(10);
/*验证删除结果*/
rbt.inorder();
return 0;
}
执行结果:
[root workspace]#g++ rbtree.cpp
[root workspace]#./a.out
0 1 2 3 4 5 6 7 8 9 10
0 1 2 3 4 5 6 7 8 9
带注释版本代码:
#define BLACK 1
#define RED 0
#include <iostream>
using namespace std;
/*红黑树结点结构:值,颜色,左孩子结点,右孩子结点,父结点*/
struct Node {
int value;
bool color;
Node *leftTree, *rightTree, *parent;
/*C++构造函数初始化列表*/
/*常成员和引用成员变量初始化必须使用初始化列表*/
Node() : value(0), color(RED), leftTree(NULL), rightTree(NULL), parent(NULL) { }
Node* grandparent() {
if(parent == NULL){
return NULL;
}
return parent->parent;
}
Node* uncle() {
if(grandparent() == NULL) {
return NULL;
}
if(parent == grandparent()->rightTree)
return grandparent()->leftTree;
else
return grandparent()->rightTree;
}
Node* sibling() {
if(parent->leftTree == this)
return parent->rightTree;
else
return parent->leftTree;
}
};
class bst {
private:
/*针对结点p右翻转*/
void rotate_right(Node *p){
Node *gp = p->grandparent();
Node *fa = p->parent;
Node *y = p->rightTree;
fa->leftTree = y;
if(y != NIL)
y->parent = fa;
p->rightTree = fa;
fa->parent = p;
if(root == fa)
root = p;
p->parent = gp;
if(gp != NULL){
if(gp->leftTree == fa)
gp->leftTree = p;
else
gp->rightTree = p;
}
}
/*针对结点p左翻转*/
void rotate_left(Node *p){
if(p->parent == NULL){
root = p;
return;
}
Node *gp = p->grandparent();
Node *fa = p->parent;
Node *y = p->leftTree;
fa->rightTree = y;
if(y != NIL)
y->parent = fa;
p->leftTree = fa;
fa->parent = p;
if(root == fa)
root = p;
p->parent = gp;
if(gp != NULL){
if(gp->leftTree == fa)
gp->leftTree = p;
else
gp->rightTree = p;
}
}
void inorder(Node *p){
if(p == NIL)
return;
if(p->leftTree)
inorder(p->leftTree);
/*打印结点值和对应颜色,方便验证问题*/
cout << p->value << " "<< outputColor(p->color)<<endl;
if(p->rightTree)
inorder(p->rightTree);
}
string outputColor (bool color) {
return color ? "BLACK" : "RED";
}
Node* getSmallestChild(Node *p){
if(p->leftTree == NIL)
return p;
return getSmallestChild(p->leftTree);
}
bool delete_child(Node *p, int data){
if(p->value > data){
if(p->leftTree == NIL){
return false;
}
return delete_child(p->leftTree, data);
} else if(p->value < data){
if(p->rightTree == NIL){
return false;
}
return delete_child(p->rightTree, data);
} else if(p->value == data){
if(p->rightTree == NIL){
delete_one_child (p);
return true;
}
Node *smallest = getSmallestChild(p->rightTree);
swap(p->value, smallest->value);
delete_one_child (smallest);
return true;
}else{
return false;
}
}
void delete_one_child(Node *p){
Node *child = p->leftTree == NIL ? p->rightTree : p->leftTree;
if(p->parent == NULL && p->leftTree == NIL && p->rightTree == NIL){
p = NULL;
root = p;
return;
}
if(p->parent == NULL){
delete p;
child->parent = NULL;
root = child;
root->color = BLACK;
return;
}
if(p->parent->leftTree == p){
p->parent->leftTree = child;
} else {
p->parent->rightTree = child;
}
child->parent = p->parent;
if(p->color == BLACK){
if(child->color == RED){
child->color = BLACK;
} else
delete_case (child);
}
delete p;
}
void delete_case(Node *p){
if(p->parent == NULL){
p->color = BLACK;
return;
}
if(p->sibling()->color == RED) {
p->parent->color = RED;
p->sibling()->color = BLACK;
if(p == p->parent->leftTree)
//rotate_left(p->sibling());
rotate_left(p->parent);
else
//rotate_right(p->sibling());
rotate_right(p->parent);
}
if(p->parent->color == BLACK && p->sibling()->color == BLACK
&& p->sibling()->leftTree->color == BLACK && p->sibling()->rightTree->color == BLACK) {
p->sibling()->color = RED;
delete_case(p->parent);
} else if(p->parent->color == RED && p->sibling()->color == BLACK
&& p->sibling()->leftTree->color == BLACK && p->sibling()->rightTree->color == BLACK) {
p->sibling()->color = RED;
p->parent->color = BLACK;
} else {
if(p->sibling()->color == BLACK) {
if(p == p->parent->leftTree && p->sibling()->leftTree->color == RED
&& p->sibling()->rightTree->color == BLACK) {
p->sibling()->color = RED;
p->sibling()->leftTree->color = BLACK;
rotate_right(p->sibling()->leftTree);
} else if(p == p->parent->rightTree && p->sibling()->leftTree->color == BLACK
&& p->sibling()->rightTree->color == RED) {
p->sibling()->color = RED;
p->sibling()->rightTree->color = BLACK;
rotate_left(p->sibling()->rightTree);
}
}
p->sibling()->color = p->parent->color;
p->parent->color = BLACK;
if(p == p->parent->leftTree){
p->sibling()->rightTree->color = BLACK;
rotate_left(p->sibling());
} else {
p->sibling()->leftTree->color = BLACK;
rotate_right(p->sibling());
}
}
}
void insert(Node *p, int data){
if(p->value >= data){
if(p->leftTree != NIL)
insert(p->leftTree, data);
else {
Node *tmp = new Node();
tmp->value = data;
tmp->leftTree = tmp->rightTree = NIL;
tmp->parent = p;
p->leftTree = tmp;
insert_case (tmp);
}
} else {
if(p->rightTree != NIL)
insert(p->rightTree, data);
else {
Node *tmp = new Node();
tmp->value = data;
tmp->leftTree = tmp->rightTree = NIL;
tmp->parent = p;
p->rightTree = tmp;
insert_case (tmp);
}
}
}
void insert_case(Node *p){
if(p->parent == NULL){
root = p;
p->color = BLACK;
return;
}
if(p->parent->color == RED){
if(p->uncle()->color == RED) {
p->parent->color = p->uncle()->color = BLACK;
p->grandparent()->color = RED;
insert_case(p->grandparent());
} else {
if(p->parent->rightTree == p && p->grandparent()->leftTree == p->parent) {
rotate_left(p);
p->color = BLACK;
p->leftTree->color = p->rightTree->color = RED;
} else if(p->parent->leftTree == p && p->grandparent()->rightTree == p->parent) {
rotate_right(p);
p->color = BLACK;
p->leftTree->color = p->rightTree->color = RED;
} else if(p->parent->leftTree == p && p->grandparent()->leftTree == p->parent) {
p->parent->color = BLACK;
p->grandparent()->color = RED;
rotate_right(p->parent);
} else if(p->parent->rightTree == p && p->grandparent()->rightTree == p->parent) {
p->parent->color = BLACK;
p->grandparent()->color = RED;
rotate_left(p->parent);
}
}
}
}
void DeleteTree(Node *p){
if(!p || p == NIL){
return;
}
DeleteTree(p->leftTree);
DeleteTree(p->rightTree);
delete p;
}
public:
bst() {
NIL = new Node();
NIL->color = BLACK;
root = NULL;
}
~bst() {
if (root)
DeleteTree (root);
delete NIL;
}
void inorder() {
if(root == NULL)
return;
inorder(root);
cout << endl;
}
void insert (int x) {
if(root == NULL){
root = new Node();
root->color = BLACK;
root->leftTree = root->rightTree = NIL;
root->value = x;
} else {
insert(root, x);
}
}
bool delete_value (int data) {
return delete_child(root, data);
}
private:
Node *root, *NIL;
};
int main()
{
bst rbt;
int i = 0;
/*插入0到10*/
for(;i <= 10;i++){
rbt.insert(i);
}
/*验证插入结果*/
rbt.inorder();
/*删除10*/
rbt.delete_value(10);
/*验证删除结果*/
rbt.inorder();
return 0;
}