红黑树(Red Black Tree) 是一种自平衡二叉查找树,典型的用途是实现关联数组。
它是在1972年由Rudolf Bayer发明的,当时被称为平衡二叉B树(symmetric binary B-trees)。后来,在1978年被 Leo J. Guibas 和 Robert Sedgewick 修改为如今的“红黑树”。
红黑树和AVL树类似,都是在进行插入和删除操作时通过特定操作保持二叉查找树的平衡,从而获得较高的查找性能。
它虽然是复杂的,但它的最坏情况运行时间也是非常良好的,并且在实践中是高效的: 它可以在O(log n)时间内做查找,插入和删除,这里的n 是树中元素的数目。
红黑树是每个节点都带有颜色属性的二叉查找树,颜色或红色或黑色。在二叉查找树强制一般要求以外,对于任何有效的红黑树我们增加了如下的额外要求:
性质1. 节点是红色或黑色。
性质2. 根节点是黑色。
性质3 每个叶节点(NIL节点,空节点)是黑色的。
性质4 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)
性质5. 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。
这些约束强制了红黑树的关键性质: 从根到叶子的最长的可能路径不多于最短的可能路径的两倍长。结果是这个树大致上是平衡的。因为操作比如插入、删除和查找某个值的最坏情况时间都要求与树的高度成比例,这个在高度上的理论上限允许红黑树在最坏情况下都是高效的,而不同于普通的二叉查找树。
要知道为什么这些特性确保了这个结果,注意到性质4导致了路径不能有两个毗连的红色节点就足够了。最短的可能路径都是黑色节点,最长的可能路径有交替的红色和黑色节点。因为根据性质5所有最长的路径都有相同数目的黑色节点,这就表明了没有路径能多于任何其他路径的两倍长。
在很多树数据结构的表示中,一个节点有可能只有一个子节点,而叶子节点不包含数据。用这种范例表示红黑树是可能的,但是这会改变一些属性并使算法复杂。为此,本文中我们使用 "nil 叶子" 或"空(null)叶子"(即哨兵节点),如上图所示,它不包含数据而只充当树在此结束的指示。这些节点在绘图中经常被省略,导致了这些树好象同上述原则相矛盾,而实际上不是这样。与此有关的结论是所有节点都有两个子节点,尽管其中的一个或两个可能是空叶子。
#include<iostream>
using namespace std;
typedef struct
{
Node* left;
Node *right;
Node *p;
int key;
char color;
} Node;
class RBTree
{
private:
Node * T;
Node *nil;
public:
Node * Tree_MIN(Node *x)
{
while (x->left != NULL)
{
x = x->left;
}
return x;
}
Node * Tree_MAX(Node *x)
{
while (x->right != NULL)
{
x = x->right;
}
return x;
}
void INORED_TREE_WALK(Node* x)
{
INORED_TREE_WALK(x->left);
cout << x->key << " ";
INORED_TREE_WALK(x->right);
}
Node* Tree_Search(Node* x, int k)
{
while (x != NULL && k != x->key)
{
if (k < x->key)
x = x->left;
else
x = x->right;
}
return x;
}
Node * Tree_SUCCESSOR(Node *x)
{
if (x->right != NULL)
return Tree_SUCCESSOR(x->right);
Node *y = x->p;
while (y != NULL && y->right == x)
{
x = x->p;
y = x->p;
}
return y;
}
void Left_Rotate(Node *& T,Node *&x)
{
Node * y = x->right;
x->right = y->left;
if(y->left!=nil)//如果右孩子的左孩子不为哨兵节点的情况
y->left->p = x;
x->p = y;
y->left = x;
y->p = x->p;
if (x->p == nil)//x为根节点的情况
T = y;
else if (x == x->p->left)
{
x->p->left = y;
}
else
{
x->p->left = y;
}
}
void Right_Rotate(Node *& T, Node *&x)
{
Node *y = x->left;
if(y->right!=nil)//如果左孩子的右孩子不为哨兵节点的情况
y->right->p = x;
x->left = y->right;
x->p = y;
y->right = x;
if (x->p == nil)
T = y;
else if (x == x->p->left)
y = x->p->left;
else
y = x->p->right;
}
void RE_Insert(Node * &T, Node *&x)
{
Node *m = T;
Node *n = nil;
while (m != nil)
{
n = m;
if (x->key > n->key)
m = n->right;
else
m = n->left;
}
x->p = n;
if (n == nil)
T = x;
else if (x->key > n->key)
x = n->right;
else
x = n->left;
x->color = 'R';
x->left = nil;
x->right = nil;
RB_Insert_Fixup(T, x);
}
void RB_Insert_Fixup(Node *&T, Node *&x)
{
while (x->p->color = 'R')
{
if (x->p == x->p->p->left)
{
Node *y = x->p->p->right;
if (y->color == 'R')
{
x->p->color = 'B';
x->p->p->left->color = 'B';
x->p->p->color = 'R';
x = x->p->p;
}
else if (x == x->p->right)
{
x = x->p;
Left_Rotate(T, x);
}
x->p->color = 'B';
x->p->p->color = 'R';
Right_Rotate(T, x->p->p);
}
else
{
Node *y = x->p->p->left;
if (y->color == 'R')
{
x->p->color = 'B';
x->p->p->left->color = 'B';
x->p->p->color = 'R';
x = x->p->p;
}
else if (x == x->p->left)
{
x = x->p;
Right_Rotate(T, x);
}
x->p->color = 'B';
x->p->p->color = 'R';
Left_Rotate(T, x->p->p);
}
T->color = 'B';
}
}
void RB_Transplant(Node *&T, Node *&u, Node *&v)
{
if (u->p == nil)
T = v;
else if (u == u->p->left)
u->p->left = v;
else if (u == u->p->right)
u->p->right = v;
v->p = u->p;
}
void RB_Delete(Node *&T, Node *&x)
{
Node *y = x;
y->color = x->color;
if (x->left == nil)
{
Node *m = x->right;
RB_Transplant(T, x, m);
}
else if (x->right == nil)
{
Node *m = x->left;
RB_Transplant(T, x, m);
}
else
{
Node *n = Tree_MIN(x->right);
y->color = n->color;
Node *m = n->right;
if (n->p == x)//出现这种情况的时候,是一个直线的情况,else中的句子会有问题,所以要改变一点
m->p = n;
else
{
RB_Transplant(T, n, n->right);
n->right = x->right;
x->right->p = n;
}
RB_Transplant(T, x, n);
n->left = x->left;
x->left->p = x;
n->color = x->color;
if (y->color = 'B')
RB_Delete_Fixup(T, m);
}
}
void RB_Delete_Fixup(Node*&T, Node*&x)
{
while (x!=T&&x->color=='B')
{
if (x == x->p->left)
{
Node* w = x->p->right;
if (w->color == 'R')
{
w->color = 'B';
x->p->color = 'R';
Left_Rotate(T, x->p);
w = x->p->right;
}
if (w->left->color == 'B'&&w->right->color == 'B')
{
w->color = 'R';
x = x->p;
}
else if (w->right->color == 'B')
{
w->left->color = 'B';
w->color = 'R';
Right_Rotate(T, w);
w = x->p->right;
}
w->color = 'R';
x->p->color = 'B';
Left_Rotate(T, x->p);
w->right->color = 'B';
x = T;
}
else
{
Node* w = x->p->left;
if (w->color == 'R')
{
w->color = 'B';
x->p->color = 'R';
Right_Rotate(T, x->p);
w = x->p->left;
}
if (w->right->color == 'B'&&w->left->color == 'B')
{
w->color = 'R';
x = x->p;
}
else if (w->left->color == 'B')
{
w->right->color = 'B';
w->color = 'R';
Left_Rotate(T, w);
w = x->p->left;
}
w->color = 'R';
x->p->color = 'B';
Right_Rotate(T, x->p);
w->left->color = 'B';
x = T;
}
}
x->color = 'B';
}
};