红黑树在每个节点上,增加一个颜色属性,可以是RED或BLACK,由于红黑树的性质,可以保证没有一条路径会比其他路径长出倍,因此是”近似平衡“的,但是红黑树通常能导致良好的平衡状态,经验告诉我们,红黑树的搜索平均效率与AVL树相等
红黑树的性质:
1.每个结点或者是红色,或者是黑色;
2.根结点是黑色
3.每个叶结点(NULL)是黑色
4.如果一个结点是红色的,则它的两个子结点都是黑色的
5.对每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相同数目的黑色结点
红黑树的实现策略:
增加哨兵:T.nil来代表NIL,其中T.nil是与普通结点具有相同属性的对象,所有指向NIL的指针都用指向T.nil的指针替换(主要原因是NIL无法加颜色)
我们可以像图(a)一样,为每一个叶结点增加哨兵,这样每个NIL的父结点都有良好的定义,但是会浪费大量空间,所以我们只用一个哨兵T.nil来代表所有的NIL:所有的叶结点和根结点的父结点。
可能大家会有疑问,为什么要定义一个T.nil呢?直接用NULL来表示,我们默认为是黑色不就行了吗?STL中确实没有这个哨兵,但是,stl中没有删除操作------据我所知,T.nil的最大作用在于删除操作------它的父结点可以改变为任何一个节点,用于回溯其父结点。
在红黑树的实现中,能够改变子树高度,也就是能够使其不同于一般二叉搜索树的操作是:旋转。旋转可以改变子树的高度,维持红黑树的性质:
左旋(x,y都不是T.nil)提升y,降低x;主要是交换好各自的父子关系:
LEFT-ROTATE(T,x)
y=x.right
x.right=y.left
if y.left!=T.nil
y.left.p=x
y.p=x.p
if x.p==T.nil//x为根
T.root=y
else if x==x.p.left
x.p.left=y
else
x.p.right=y
y.left=x
x.p=y
右旋:
RIGHT-ROTATE(T,x)
y=x.left
x.left=y.right
if y.right!=T.nil
y.right.p=x
y.p=x.p
if x.p=T.nil
T.root=y
elseif x==x.p.left
x.p.left=y
else
x.p.right=y
y.right=x
x.p=y
插入操作:
插入操作分为两部分:插入和调整;
假设要插入的节点都为红色,那么红黑树的性质1,3,5不变,当原来的树为空时,会改变性质2;还有可能改变的性质是性质四;
我们之后进行的调整工作就是能够再次使性质2和4保持。
RB-INSERT(T,z)
y=T.nil
x=T.root
while x!=T.nil
y=x
if z.key<x.key
x=x.left
else
x=x.right
z.p=y
if y==T.nil
T.root=z
elseif z.key<y.key
y.left=z
else y.right=z
//下面是比一般二叉搜索树多出来的部分
z.left=T.nil
z.right=T.nil
z.color=RED
RB-INSERT-FIXUP(T,z)//调整
调整的原则是把破坏规则的节点尽量上移,最坏情况下如果上移到根结点,只要把根结点设置成黑色,就万事大吉。
调整发生在:当插入结点的父结点是红结点时,此时必有祖父结点为黑色,叔父结点未知:
此时有六种情况,下面分析当插入结点的父结点是祖父节点的左孩子时的三种情况:
case1:叔节点为红色(插入节点为左侧插入---外插,或者为右侧插入---内插)
这时候,只要把c遍为红色,B,D变为黑色,blak-height不变,此时,唯一有可能违反性质的节点是C,所以破坏规则的节点上移了。
case2:叔节点是黑色,插入节点是右侧插入---内插:
我们将内侧插入转变为外侧插入,以插入节点的父结点A做左旋,此时令z指向B,变为外侧插入,即第三种情况
case3:叔节点是黑色,插入节点是左侧插入---外插
此时以C为支点,做右旋,然后把B变成黑色,C变成红色即可。
RB-INSERT-FIXUP(T,z)
while z.p.color==RED
if z.p==z.p.p.left
y=z.p.p.right//叔父结点
if y.color==RED//case1
z.p.color=BLACK
y.color=BLACK
z.p.p.color=RED
z=z.p.p
elseif z=z.p.right//case2
z=z.p
LEFT-ROTATE(T,z)
//此时成为外侧插入,执行case3
z.p.color=BLACK
z.p.p.color=RED
RIGHT-ROTATE(T,z.p.p)
else //插入节点的父结点为祖父节点的右孩子
将[left]与[right]互换
T.root.color=BLACK
对于删除操作,也分为删除和调整两部分
首先是删除操作的辅助程序-TRANSPLANT,将以u为根的子树用以v为根的子树替换,通常适用于v是u的唯一子结点时
RB-TRANSPLANT(T,u,v)
if u.p==T.nil
T.root=v
elseif u==u.p.left
u.p.left=v
else u.p.rigth=v
v.p=u.p
删除程序同二叉搜索树,[见二叉搜索树代码解析]
调整:
这次的焦点放在-y:从树中删除的节点或者移至树中的节点(即原来要删除节点的后继)
当y为红色时,直接删除,不违反性质;
当y为黑色时,对于y为删除节点,那么包含y的任意简单路径上黑节点少1;对于y为移动节点,同理;
这里我们采用的策略是:
令x为删除或移动y后顶替位置的元素,那么设x还有一重黑色,但是现在的问题变为:x既不是红色也不是黑色,违反性质1.
当x是其父节点的左孩子时:
case0:
当x是单重黑色,单重红色时,直接令x为黑色,则完成任务;
case1:x是双重黑色,x的兄弟节点w是红色,此时必有x父结点为黑色:
此时我们要做的是:以x的父结点B左旋,使B的颜色变为红色,w的颜色变为黑色,此时除性质1外,其他性质保持
<经过case1之后,x的兄弟节点为黑色>
case2:x是双重黑色,x的兄弟节点w是黑色,且w的两个子结点都是黑色:
此时,令w的颜色变为红色,去掉x的一重黑色,将x父结点上加上一重黑色即可,此时,唯一违反性质的节点是x的父结点。
case3:x是双重黑色,x的兄弟节点w是黑色,w的左孩子是黑色,右孩子是红色:
此时我们将w右旋,且C变为新的w,C的颜色变为黑色,D的颜色变为红色,此时转到第四种情况
case4:x是双重黑色,兄弟节点w是黑色,且w的右孩子是红色:
此时,可以去掉x的一重黑色--如图。
RB-DELETE-FIXUP
while x!=T.root and x.color==BLACK//此时为两重黑色
if x=x.p.left//当x为父结点的左孩子
w=x.p.right//x的兄弟节点
if w.color==RED//case1
w.color=BLACK
x.p.color=RED
LEFT-ROTATE(T,x.p)
w=x.p.right
if w.left.color==BLACK and w.right.color=BLACK//case2
w.color=RED
x=x.p
elseif w.right.color==BLACK//case3
w.left.color=BLACK
w.color=RED
RIGHT-ROTATE(T,w)
w=x.p.right
//case4
w.color=x.p.color
x.p.color=BLACK
w.right.color=BLACK
LEFT-ROTATE(T,x.p)
x=T.root
else
left与right互换
x.color=bBLACK//case0
下面附一份STL版的红黑树,简单版的红黑树把二叉搜索树扩展一下即可得到:
//下面使用stl版本的红黑树,简单版的红黑树跟二叉搜索树基本相同,除了插入和删除稍麻烦外。
#include"myconstruct.h"
#include"myiterator.h"
#include"mymemory.h"
#include<utility>
//表示颜色
typedef bool _rb_tree_color_type;
const _rb_tree_color_type _rb_tree_red=false;//红色为0
const _rb_tree_color_type _rb_tree_black=true;//黑色为1
//节点结构
template<typename Value>
struct _rb_tree_node
{
typedef _rb_tree_color_type color_type;
typedef _rb_tree_node<Value> node_type;
color_type color;
Value value_field;
node_type* parent;
node_type* left;
node_type* right;
static node_type* minimum(node_type* x)
{
while(x->left!=0) x=x->left;
return x;
}
static node_type* maximum(node_type* x)
{
while(x->right!=0) x=x->right;
return x;
}
};
//迭代器设计:
template<typename Value,typename Ref,typename Ptr>
struct _rb_tree_iterator
{
typedef bidirectional_iterator_tag iterator_category;
typedef size_t difference_type;
typedef _rb_tree_node<Value> node_type;
typedef Value value_type;
typedef Ref reference;
typedef Ptr pointer;
typedef _rb_tree_iterator<Value,Value&,Value*> iterator;
typedef _rb_tree_iterator<Value,const Value&,const Value*> const_iterator;
typedef _rb_tree_iterator<Value,Ref,Ptr> self;
node_type* node;//与容器的联系
_rb_tree_iterator(){}
_rb_tree_iterator(node_type* x){node=x;}
_rb_tree_iterator(const iterator& it){node=it.node;}
reference operator*() const {return node->value_field;}
pointer operator->() const{return &(operator*());}
self& operator++(){increment();return *this;}
self operator++(int){self tmp=*this;increment();return tmp;}
self& operator--(){decrement();return *this;}
self operator--(int){self tmp=*this;decrement();return tmp;}
bool operator== (const self& x)const{return x.node==node;}
bool operator!=(const self& x)const{return x.node!=node;}
private://辅助程序
void increment();//后继
void decrement();//前驱
};
//-------------------------------------------------------------------------------------------
/*返回中序遍历时,x的后继,其中二叉搜索树的结构允许我们不通过任何关键字的比较获得O(h):
*case1:如果x的右子树非空,那么后继y是x右子树的最小元素
*case2:如果x的右子树为空:
* case1’:如果x是父结点的左孩子,那么x的后继为父结点
* case2’:如果x是父结点y的右孩子,那么寻找这样一个节点z,使x,y所在的子树为z的左子树
*/
template<typename Value,typename Ref,typename Ptr>
void _rb_tree_iterator<Value,Ref,Ptr>::increment()
{
if(node->right!=0){//case1
node=node_type::minimum(node->right);
}else{//case2
//case1':
node_type* y= node->parent;
//case2':
while(node==y->right){
node=y;
y=y->parent;
}
if(node->right!=y)
node=y;
}
}
//----------------------------------------------------------------------------------------
/*返回中序遍历时,x的前驱:O(h)
*case1:x有左子树,那么x的前驱是x左子树的最大值;
*case2:x无左子树
* case1’:x是其父结点y的右孩子,那么前驱为y
* case2’:x是其父结点y的左孩子,寻找祖先z,使x,y所在子树是z的右子树
*/
template<typename Value,typename Ref,typename Ptr>
void _rb_tree_iterator<Value,Ref,Ptr>::decrement()
{
if(node->color==_rb_tree_red&&node->parent->parent==node)//header
node=node->right;
else if(node->left!=0){//case1
node=node_type::maximum(node->left);
}else{//case2
//case1':
node_type* y=node->parent;
//case2':
while(node==y->left){
node=y;
y=y->parent;
}
node=y;
}
}
//----------------------------------------------------------------------------------------------
//红黑树
template<typename Key,typename Value,typename KeyOfValue,typename Compare,
typename Alloc=alloc>
class rb_tree
{
protected:
typedef void* void_pointer;
typedef _rb_tree_node<Value> node_type;
typedef simple_alloc<node_type,Alloc> rb_tree_node_allocator;
typedef _rb_tree_color_type color_type;
public:
typedef Key key_type;
typedef Value value_type;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef size_t size_type;
typedef size_t difference_type;
typedef _rb_tree_iterator<value_type,reference,pointer> iterator;
protected://内存管理
//配置一个节点
node_type* get_node(){return rb_tree_node_allocator::allocate();}
//释放一个节点
void put_node(node_type* p){rb_tree_node_allocator::deallocate(p);}
node_type* create_node(const value_type& x){node_type* tmp=get_node();
construct(&tmp->value_field,x);
return tmp;
//可以直接使用new,不过需要节点定义构造函数
}
node_type* clone_node(node_type* x);//复制一个节点
void destroy_node(node_type* p){destroy(&p->value_field);//析构内容
put_node(p);//可以直接使用delete,但是需要定义析构函数
}
protected:
size_type node_count;
node_type* header;//红色,技巧性实现
Compare key_compare;//函数对象,用于比较
node_type*& root() const{return header->parent;}
node_type*& leftmost() const{return header->left;}
node_type*& rightmost()const{return header->right;}
//用于取得节点的值
static node_type*& left(node_type* x){return x->left;}
static node_type*& right(node_type* x){return x->right;}
static node_type*& parent(node_type* x){return x->parent;}
static reference value(node_type* x){return x->value_field;}
static const Key& key(node_type* x){return KeyOfValue()(value(x));}
static color_type& color(node_type* x){return x->color;}
private:
iterator _insert(node_type* x,node_type* y,const value_type& v);
void init();
void clear();
public://构造和析构
rb_tree(const Compare& comp=Compare())
:node_count(0),key_compare(comp){init();}
~rb_tree(){clear();put_node(header);}
rb_tree<Key,Value,KeyOfValue,Compare,Alloc>&
operator=(const rb_tree<Key,Value,KeyOfValue,Compare,Alloc>& x);
public:
Compare key_comp() const{return key_compare;}
iterator begin(){return leftmost();}//红黑树的最小元素
iterator end(){return header;}//header作为终点
bool empty()const{return node_count==0;}
size_type size() const{return node_count;}
size_type max_size() const{return size_type(-1);}//?
public:
//不允许节点值重复
std::pair<iterator,bool> insert_unique(const value_type& x);
//允许节点值重复
iterator insert_equal(const value_type& x);
iterator find(const Key& k);
};
//----------------------------------------------------------------------------------------
template<typename Key,typename Value,typename KeyOfValue,typename Compare,
typename Alloc>
typename rb_tree<Key,Value,KeyOfValue,Compare,Alloc>::node_type*
rb_tree<Key,Value,KeyOfValue,Compare,Alloc>::clone_node(node_type* x)
{
node_type tmp=create_node(x->value_field);
tmp->color=x->color;
tmp->left=0;
tmp->right=0;
return tmp;
}
//----------------------------------------------------------------------------------------------
template<typename Key,typename Value,typename KeyOfValue,typename Compare,
typename Alloc>
void rb_tree<Key,Value,KeyOfValue,Compare,Alloc>::init()
{//header左右子结点指向自己
header=get_node();
color(header)=_rb_tree_red;
root()=0;
leftmost()=header;
rightmost()=header;
}
//----------------------------------------------------------------------------------------
template<typename Key,typename Value,typename KeyOfValue,typename Compare,
typename Alloc>
typename rb_tree<Key,Value,KeyOfValue,Compare,Alloc>::iterator
rb_tree<Key,Value,KeyOfValue,Compare,Alloc>::insert_equal(const Value& v)
{
node_type* y=header;
node_type* x=root();
while(x!=0){//从根节点开始
y=x;
x=key_compare(KeyOfValue()(v),key(x))?left(x):right(x);
//遇大往左走,遇小于等于往右走
}
return _insert(x,y,v);//y为插入点的父结点,x为插入点
}
//---------------------------------------------------------------------------------------------
template<typename Key,typename Value,typename KeyOfValue,typename Compare,
typename Alloc>
std::pair<typename rb_tree<Key,Value,KeyOfValue,Compare,Alloc>::iterator,bool>
rb_tree<Key,Value,KeyOfValue,Compare,Alloc>::insert_unique(const Value& v)
{
node_type* y=header;
node_type* x=root();
bool comp=true;
while(x!=0){
y=x;
comp=key_compare(KeyOfValue()(v),key(x));
x=comp?left(x):right(x);
}
iterator j=iterator(y);
if(comp){//离开while时,comp为真,插于左侧
if(j==begin())//如果插入点父结点为最左节点
return std::pair<iterator,bool>(_insert(x,y,v),true);
else
--j;
}
if(key_compare(key(j.node),KeyOfValue()(v)))//新键值不与既有节点值重复
return std::pair<iterator,bool>(_insert(x,y,v),true);
//至此,则重复
return std::pair<iterator,bool>(j,false);
}
//------------------------------------------------------------------------------------
template<typename Key,typename Value,typename KeyOfValue,typename Compare,
typename Alloc>
typename rb_tree<Key,Value,KeyOfValue,Compare,Alloc>::iterator
rb_tree<Key,Value,KeyOfValue,Compare,Alloc>::_insert(node_type* x,node_type* y,
const Value& v)
{
node_type* x_copy=x;
node_type* y_copy=y;
node_type* z;
if(y==header||x!=0||key_compare(KeyOfValue()(v),key(y))){
z=create_node(v);
left(y)=z;
if(y==header){
root()=z;
rightmost()=z;
}else if(y==leftmost()){
leftmost()=z;
}
}else{
z=create_node(v);
right(y)=z;
if(y==rightmost()){
rightmost()=z;
}
}
parent(z)=y;
left(z)=0;
right(z)=0;
z->color=_rb_tree_red;
_rb_insert_fixup(z,header->parent);
++node_count;
return iterator(z);
}
//--------------------------------------------------------------------------------------------
template<typename Key,typename Value,typename KeyOfValue,typename Compare,
typename Alloc>
typename rb_tree<Key,Value,KeyOfValue,Compare,Alloc>::iterator
rb_tree<Key,Value,KeyOfValue,Compare,Alloc>::find(const Key& k)
{
node_type* y=header;
node_type* x=root();
while(x!=0){
if(!key_compare(key(x),k))//x大于k
y=x,x=left(x);
else
x=right(x);
}
iterator j=iterator(y);
return (j==end()||key_compare(k,key(j.node)))?end():j;
}
//------------------------------------------------------------------------------------------
template<typename Key,typename Value,typename KeyOfValue,typename Compare,
typename Alloc>
void rb_tree<Key,Value,KeyOfValue,Compare,Alloc>::clear()
{
for(iterator it=begin(),next=++it;it!=end();++next){
destroy_node(it.node);
it=next;
}
}
//-----------------------------------------------------------------------------------------
//全局函数1--左旋
template<typename Value>
void _rb_left_rotate(_rb_tree_node<Value>* x,_rb_tree_node<Value>*& root)
{
_rb_tree_node<Value>* y=x->right;
x->right=y->left;
if(y->left!=0){
y->left->parent=x;
}
y->parent=x->parent;
if(x==root)
root=y;
else if(x==x->parent->left){
x->parent->left=y;
}else
x->parent->right=y;
y->left=x;
x->parent=y;
}
//全局函数2-右旋
template<typename Value>
void _rb_right_rotate(_rb_tree_node<Value>* x,_rb_tree_node<Value>*& root)
{
_rb_tree_node<Value>* y=x->left;
x->left=y->right;
if(y->right!=0)
y->right->parent=x;
y->parent=x->parent;
if(x==root)
root=y;
else if(x==x->parent->right)
x->parent->right=y;
else
x->parent->left=y;
y->right=x;
x->parent=y;
}
//----------------------------------------------------------------------------------------
//全局函数三
template<typename Value>
void _rb_insert_fixup(_rb_tree_node<Value>* x,_rb_tree_node<Value>*& root)
{
while(x!=root && x->parent->color==_rb_tree_red){
if(x->parent==x->parent->parent->left){
_rb_tree_node<Value>* y=x->parent->parent->right;//y为x的叔父结点
if(y&&y->color==_rb_tree_red){//case1
x->parent->color=_rb_tree_black;
y->color=_rb_tree_black;
x->parent->parent->color=_rb_tree_red;
x=x->parent->parent;
}else{
if(x==x->parent->right){//case2
x=x->parent;
_rb_left_rotate(x,root);
}
//case3
x->parent->color=_rb_tree_black;
x->parent->parent->color=_rb_tree_red;
_rb_right_rotate(x->parent->parent,root);
}
}
else{//对称的三种情况
_rb_tree_node<Value>* y=x->parent->parent->left;
if(y&&y->color==_rb_tree_red){//case1
x->parent->color=_rb_tree_black;
y->color=_rb_tree_black;
x->parent->parent->color=_rb_tree_red;
x=x->parent->parent;
}else{
if(x==x->parent->left){//case2
x=x->parent;
_rb_right_rotate(x,root);
}
//case3
x->parent->color=_rb_tree_black;
x->parent->parent->color=_rb_tree_red;
_rb_left_rotate(x->parent->parent,root);
}
}
}
root->color=_rb_tree_black;
}