红黑树的性质:
1.每个结点或是红色的,或是黑色的
2.根结点都是黑色的
3.如果一个结点是红色的,则它的两个子结点都是黑色的。
4.对于每个结点,从该节点到其所有后代的NULL的简单路径上,均包含相同数目的黑色结点
红黑树的插入:
对于红黑树T,将新结点z插到T中,就像普通的二叉查找树样,先把z插入到树中,然后再把z着为红色(因为若把该节点涂成黑色,则将会建立一条更长的黑结点路径)。若z的父结点为黑色,则不会破坏红黑树性质,完成插入;若父结点为红色,则破坏红黑树的性质。当T为空,那么在就是跟结点,违反了性质2;若T不为空,违反性质3。
红黑树的插入分下面几种情况(T为空时,就不列出来,因为直接把z结点作为根结点,并且把z涂成黑色即可)圆圈表示黑色,正方形表示红色:
一、z结点的父结点是z祖父的左儿子(其中的z指向新插入的结点k3)
(一)z的叔结点是空
1. z是左儿子
2. z是右儿子
(二) z的叔结点不为空
1. z的叔结点为红色,如下图通过变换,将z的指针上移,指向k1。然后以k1为新的z进入下次循环,调整红黑树,使得树满足红黑树的性质
2. z的叔结点为黑色,其中分为,z为左儿子和右儿子,其变换图下图。当z为右儿子时,z指向k2,通过变换转化为z的结点为左儿子的情况。
对于上述的插入,当为(一)中的两种情况,通过变换后,满足红黑树的性质。在编程中通过设置flag标示来结束循环;当为(二)中2的第一种情况(即z为左儿子),通过变换后,满足红黑树的性质,通过判断z的父结点是否为黑色来结束循环。其他情况中若z指向根结点,则把z的颜色涂成黑色,结束循环。
当z的父结点为z祖父结点的右儿子时,可以类似z父结点为左儿子的进行类似的变换,使得满足红黑树的性质。
红黑树的删除
红黑树的删除比红黑树的插入复杂的多。首先由二叉查找树删除的性质可知,删除的结点z一般为:z无儿子、z仅有一个左儿子、z仅有一个右儿子。因为当删除的结点有两个儿子时,总可以通过查找该结点的后继z,后继中的元素element替换该节点中的元素element。这样就把删除转化为上述的三种中的某一种情况。
下面考虑删除中的几种情况:删除结点为z
一、z为红色时
这个比较简单,由上分析可知z最多只有一个儿子,因为z为红色,要有儿子必为两个黑色儿子,这与上面分析矛盾,所以z为红色时无儿子。删除时直接删除即可,不会破坏红黑树的性质。
二、z为黑色时,且z有一个儿子或者z为根节点无儿子。
当z有一个儿子时,该结点必为红色,若为黑色,由于z是只有一个儿子的,其不满足红黑树的性质4。删除方法:直接把z儿子中的元素element代替z中的元素element,然后把z儿子结点删除;若z为根结点直接删除即可。
三、z为黑色且z无儿子(z指向的k2为要删除的结点,通过把k2的颜色变为红色然后删除,这样不会破坏红黑树的性质)
1. z的兄弟结点为红色
为了满足红黑树性质4,则其兄弟结点必有两个儿子且都为黑色。进行下面图中的调整
变换后,将k1涂成黑色,k2和A涂成红色,然后删除k2。
2. z的兄弟结点为黑色且z的父结点为黑,且兄弟结点有两个儿子结点(为了满足红黑树的性质4,则兄弟结点的儿子必为红色)
通过图中的变换后,其转化为1的情况。
3. z的兄弟结点为黑且z的父结点为黑,兄弟结点有一个右儿子
直接删除k2的结点。
4. z的兄弟结点为黑且z的父结点为黑,兄弟结点有一个左儿子
通过图中的变换,变为情况3
5. z的兄弟结点为黑且z的父结点为黑,兄弟结点无儿子,做法是:把z和z的兄弟结点涂成红色,z的父亲结点x为双黑色,然后删除z结点。接下来就是怎样把x的双黑去掉一层。此情况比较复杂,下面会做单独讨论的。
6. z的父结点为红(则z兄弟结点必为黑)且z的兄弟结点有两个儿子(其儿子必为红色,可以分析红黑树的性质得到)
通过变换后,删除k2结点
7. z的父结点为红(则z兄弟结点必为黑)且z的兄弟结点有一个左儿子(其儿子必为红色,可以分析红黑树的性质得到)
变为情况8
8. z的父结点为红(则z兄弟结点必为黑)且z的兄弟结点有一个右儿子(其儿子必为红色,可以分析红黑树的性质得到)
通过变换后,直接删除k2
9. z的父结点为红(则z兄弟结点必为黑)且z的兄弟结点无儿子
通过变换后直接删除k2。
上面分析了删除的结点k2为左儿子的情况,当删除结点为右儿子可以类比的分析。下面给出上面情况5的分析:
对于删除结点k2、k2的父亲、k2的兄弟都为黑色,为了不破坏红黑树的性质,我们可以把k2、k2的兄弟涂成红色,把k2的父亲假设为双黑色,便可以把k2结点删除,这样并未破坏红黑树的性质。令x指向z的双黑父亲结点,下面的主要任务是把x指向的结点去掉一层黑色,怎么才能去掉一层黑色呢?分为下面几种情况
下面以x是左儿子为例说明。
1. x的兄弟结点为红色
x为双黑色,为了满足红黑树性质4,x的兄弟结点后代必有黑色结点。
通过上面的变换后,其变为下述的情况2、3、4中的某一种,然后继续循环,知道满足红黑树的性质。
2. x的兄弟结点为黑色,且兄弟结点有两个儿子也都是黑色的
第一种直接把双黑x指向的A结点去除一层黑色,同时没有破坏红黑树的性质,完成任务;第二种x指向的A结点去除一层黑色,但是B结点变为双黑的,x指针上移指向B结点,进入下次循环,把B结点的黑色去除一层。
3. x的兄弟结点为黑色,且兄弟结点的左儿子为红色,右儿子为黑色(其中B的三角形表示该结点颜色可为黑、红任意一种)
通过上面的变换,转化为情况4。进入下次循环。
4. x的兄弟结点为黑色,右儿子为红色(其中B、C结点的三角形表示该结点可以为黑、红中任意一种颜色)
通过上变化后,A结点的黑色去掉一层,因为在原始图中由A的父结点到A的两个儿子黑色结点数为2(因为A为双黑的),变换后由D到A的两个儿子黑色结点数也为2(此时A只是一层黑色)。
代码如下:
rb-tree.h
#pragma once
#include<iostream>
#include<string>
using namespace std;
template<typename Comparable>
struct Node
{
Comparable element;//元素
Node* left; //指向左儿子的左指针
Node* right;//指向右儿子的右指针
Node* parent; //指向父亲结点
string color; //该结点的颜色
Node(Comparable x,Node* l,Node* r,Node* p,string c):element(x),left(l),right(r),parent(p),color(c){}
};
enum MODE
{
PRE,
MID,
POST
};
template<typename Comparable>
class rbtree
{
public:
rbtree();
rbtree(rbtree &rh);
Comparable findmin();
Comparable findmax();
void insert(Comparable x);
void remove(Comparable x);
void print(MODE mode);
private:
Node<Comparable>* root;
Node<Comparable>* findmin(Node<Comparable>* t);//寻找最小
Node<Comparable>* findmax(Node<Comparable>* t);//寻找最大
void insert(Node<Comparable>* &t);//插入
Node<Comparable>* remove(Comparable x,Node<Comparable>* &t);//删除,其中t为要删除的结点
void Lremove(Node<Comparable>* &x);
void Rremove(Node<Comparable>* &x);
void leftrotate(Node<Comparable>* t);//左旋
void rightrotate(Node<Comparable>* t);//右旋
void PrePrint(Node<Comparable>* t);
void MidPrint(Node<Comparable>* t);
void PostPrint(Node<Comparable>* t);
};
rb-tree.cpp
#include "stdafx.h"
#include"rb-tree.h"
#include<iostream>
#include<string>
using namespace std;
template<typename Comparable>
rbtree<Comparable>::rbtree()
{
root=NULL;
}
template<typename Comparable>
rbtree<Comparable>::rbtree(rbtree& rh)
{
root=rh.root;
}
template<typename Comparable>
Comparable rbtree<Comparable>::findmin()
{
return findmin(root)->element;
}
template<typename Comparable>
Node<Comparable>* rbtree<Comparable>::findmin(Node<Comparable>* t)
{
if(t==NULL)
return NULL;
else if(t->left==NULL)
return t;
else
findmin(t->left);
}
template<typename Comparable>
Comparable rbtree<Comparable>::findmax()
{
return findmax(root)->element;
}
template<typename Comparable>
Node<Comparable>* rbtree<Comparable>::findmax(Node<Comparable>* t)
{
if(t==NUUL)
return NULL;
else if(t->left==NULL)
return t;
else
findmax(t->right);
}
template<typename Comparable>
void rbtree<Comparable>::insert(Comparable x)
{
Node<Comparable>* t=new Node<Comparable>(x,NULL,NULL,NULL,"RED");
insert(t);
}
template<typename Comparable>
void rbtree<Comparable>::insert(Node<Comparable>* &z)//插入
{
Node<Comparable>* x=root;
Node<Comparable>* y=NULL;
while(x!=NULL)
{
y=x;
if(z->element<x->element)
x=x->left;
else
x=x->right;
}
z->parent=y;
if(y==NULL)
root=z;
else if(z->element<y->element)
y->left=z;
else
y->right=z;
//调整红黑树,使其满足红黑树的性质
bool flag=true;
while(flag&&(z!=root)&&(z->parent->color=="RED"))//z的父结点是红色的且,z不是根结点
{
if(z->parent==z->parent->parent->left)//z的父亲结点是祖父的左儿子时
{
if(z->parent->parent->right==NULL)//如果其叔结点为空
{
if(z==z->parent->left)
{
z->parent->color="BLACK";
z->parent->parent->color="RED";
rightrotate(z->parent->parent);
flag=false;
}
else
{
z->color="BLACK";
z->parent->parent->color="RED";
leftrotate(z->parent);
rightrotate(z->parent);
flag=false;
}
}
else
{
y=z->parent->parent->right; //是z结点的叔结点
if(y->color=="RED") //case 1: z的叔结点是红色的
{
//cout<<"0"<<endl;
z->parent->color="BLACK";
y->color="BLACK";
z->parent->parent->color="RED";
z=z->parent->parent; // z指针上移
}
else if(z==z->parent->right) //case 2: z是右儿子
{
//cout<<"1"<<endl;
z=z->parent;
leftrotate(z);
}
else
{
// cout<<"2"<<endl;
z->parent->color="BLACK"; //case 3:
z->parent->parent->color="RED";
rightrotate(z->parent->parent);
}
}
}
else //z的父亲结点是祖父的右儿子
{
if(z->parent->parent->left==NULL)//叔结点为空
{
if(z==z->parent->right)
{
z->parent->color="BLACK";
z->parent->parent->color="RED";
leftrotate(z->parent->parent);
flag=false;
}
else
{
z->color="BLACK";
z->parent->parent->color="RED";
rightrotate(z->parent);
leftrotate(z->parent);
flag=false;
}
}
else
{
y=z->parent->parent->left;//是z结点的叔结点
if(y->color=="RED") //case 1
{
// cout<<"3"<<endl;
z->parent->color="BLACK";
y->color="BLACK";
z->parent->parent->color="RED";
z=z->parent->parent; // z指针上移
}
else if(z==z->parent->right) //case 2
{
// cout<<"4"<<endl;
z->parent->color="BLACK";
z->parent->parent->color="RED";
leftrotate(z->parent->parent);
}
else //case 3:
{
z=z->parent;
rightrotate(z);
}
}
}
}
root->color="BLACK";
}
template<typename Comparable>
void rbtree<Comparable>::remove(Comparable x)
{
Node<Comparable>* z=remove(x,root);
if(z->color=="RED") //删除的结点为红色,则直接删除,不会破坏红黑树的性质
{ //因为删除的结点最多只有一个儿子结点,若删除结点为红色结点,则其必没有儿子结点。
if(z==z->parent->left)
z->parent->left=NULL;
else
z->parent->right=NULL;
delete z;
}
else //删除结点为黑色,删除会破坏红黑树的性质
{
if((z==root)||(z->left!=NULL)||(z->right!=NULL)) //z为根结点,(或者z有一个儿子,则该儿子必为红色的)
{
Node<Comparable>* temp;
if(z->left!=NULL)
{
z->element=z->left->element;
temp=z->left;
z->left=NULL;
delete temp;
}
else if(z->right!=NULL)
{
z->element=z->right->element;
temp=z->right;
z->right=NULL;
delete temp;
}
else
delete z;
}
else //z不为根结点,并且z无儿子结点
{
Node<Comparable>* temp=z;
Node<Comparable>* w=NULL; //记录z的兄弟结点,因为z结点为黑色,所以其必有兄弟结点。
bool flag=true; //标记是否把结点删除
while(flag&&z!=root&&z->color=="BLACK")//并且若z有儿子也为红色的
{
if(z==z->parent->left)//z为左儿子结点时
{
w=z->parent->right;//z的右兄弟
if(w->color=="RED") //case1:z的兄弟为红色
{
w->color="BLACK";
z->parent->color="RED";
leftrotate(z->parent);
w=z->parent->right;//左旋后,z的兄弟结点改变
if(w->left==NULL&&w->right==NULL)//w无子结点,直接改变某些结点颜色,然后删除,
{ //否则进入下次循环
z->color="RED";
w->color="RED";
z->parent->color="BLACK";
z->parent->left=NULL;
delete z;
flag=false;
}
}
else if(w->left!=NULL&&w->right!=NULL)//case 2:兄弟结点两个儿子都存在,则其必为红色
{
if(z->parent->color=="BLACK")//父结点为黑色
{
w->left->color="BLACK";
w->right->color="BLACK";
w->color="RED"; //进入下次循环,变成情况1
}
else //父结点为红色
{
z->parent->color="BLACK";
z->color="RED";
w->right->color="BLACK";
w->color="RED";
leftrotate(z->parent);
z->parent->left=NULL;
delete z;
flag=false;
}
}
else if(w->left!=NULL) //case 3:左儿子不为空,必为红色,右儿子为空
{
w->color="RED";
w->left->color="BLACK";
rightrotate(w); //进入下次循环,变成情况4
}
else if(w->right!=NULL)//case 4:兄弟结点右儿子不为空,必为红色,左儿子为空
{
z->color="RED";
if(z->parent->color=="BLACK")//父结点是黑色,要将z的右兄弟儿子变为黑色
w->right->color="BLACK";
leftrotate(z->parent);
z->parent->left=NULL;
delete z;
flag=false;
}
else //case 5:兄弟结点的两个儿子都为空
{
if(z->parent->color=="BLACK")//父结点为黑色
{
Node<Comparable>* x=z->parent;
z->color="RED";
w->color="RED";
x->left=NULL;
delete z;
if(x!=root)
{
if(x==x->parent->left)
Lremove(x);
else
Rremove(x);
flag=false;
}
else
{
flag=false;
}
}
else //父结点为红色
{
z->color="RED";
w->color="RED";
z->parent->color="BLACK";
z->parent->left=NULL;
delete z;
flag=false;
}
}
}
else //z为右儿子结点时
{
w=z->parent->left;//z的左兄弟结点
if(w->color=="RED") //case 1:
{
z->parent->color="RED";
w->color="BLACK";
rightrotate(z->parent);
w=z->parent->left;
if(w->left==NULL&&w->right==NULL)
{
z->color="RED";
w->color="RED";
z->parent->color="BLACK";
z->parent->right=NULL;
delete z;
flag=false;
}
}
else if(w->left!=NULL&&w->right!=NULL)//case 2:
{
if(z->parent->color=="BLACK")
{
w->left->color="BLACK";
w->right->color="BLACK";
w->color="RED";
}
else
{
z->parent->color="BLACK";
w->color="RED";
z->color="RED";
w->left->color="BLACK";
rightrotate(z->parent);
z->parent->right=NULL;
delete z;
flag=false;
}
}
else if(w->left!=NULL) //case 3:
{
z->color="RED";
if(z->parent->color=="BLACK")//父结点是黑色
w->left->color="BLACK";
rightrotate(z->parent);
z->parent->right=NULL;
delete z;
flag=false;
}
else if(w->right!=NULL) //case 4:
{
w->color="RED";
w->right->color="BLACK";
leftrotate(w);
}
else //case 5:
{
if(z->parent->color=="BLACK")
{
Node<Comparable>* x=z->parent;
z->color="RED";
w->color="RED";
x->right=NULL;
delete z;
if(x!=NULL)
{
if(x==x->parent->left)
Lremove(x);
else
Rremove(x);
flag=false;
}
else
{
flag=false;
}
}
else
{
w->color="RED";
z->color="RED";
z->parent->color="BLACK";
z->parent->right=NULL;
delete z;
flag=false;
}
}
}
}
}
}
}
template<typename Comparable>
Node<Comparable>* rbtree<Comparable>::remove(Comparable x,Node<Comparable>* &t)//返回要删除的结点的指针
{
if(t==NULL)
return NULL;
else if(x<t->element)
remove(x,t->left);
else if(x>t->element)
remove(x,t->right);
else if(t->left!=NULL&&t->right!=NULL)//删除结点左右指针都不是空,返回右侧中最小的元素指针
{
Node<Comparable>* temp=findmin(t->right);
t->element=temp->element;
return temp;
}
else //左右指针都为空或只有一个为空。
return t;
}
template<typename Comparable>
void rbtree<Comparable>::Lremove(Node<Comparable>* &x)//父结点是黑色且是左儿子,且兄弟结点无儿子的删除
{
bool flag=true;
Node<Comparable>* w=x->parent->right;//兄弟结点
while(flag&&x!=root)
{
if(w->color=="RED")//case 1:兄弟结点为红色
{
x->parent->color="RED";
w->color="BLACK";
leftrotate(x->parent);
w=x->parent->right;
}
else if(w->left->color=="BLACK"&&w->right->color=="BLACK")//case 2:兄弟结点为黑色,
{ //且兄弟结点两个儿子为黑色
if(x->parent->color=="RED")//父结点为红色
{
x->parent->color="BLACK";
w->color="RED";
flag=false;
}
else //父结点为黑色
{
if(x->parent==root)
{
w->color="RED";
flag=false;
}
else
{
w->color="RED";
x=x->parent; //此时x指针指向父结点,表明父结点变为双黑
w=x->parent->right;
}
}
}
else if(w->right->color=="RED") //case 3:兄弟结点右儿子是红色,左儿子是任意
{
w->color=x->parent->color;
x->parent->color="BLACK";
w->right->color="BLACK";
leftrotate(x->parent);
flag=false;
}
else //case 4:兄弟结点左儿子是红色,右儿子是黑色
{
w->color="RED";
w->left->color="BLACK";
rightrotate(w); //变成情况3
w=x->parent->right;
}
}
}
template<typename Comparable>
void rbtree<Comparable>::Rremove(Node<Comparable>* &x)//父结点是黑色且是右儿子,且兄弟结点无儿子的删除
{
bool flag=true;
Node<Comparable>* w=x->parent->left;
while(flag&&x!=root)
{
if(w->color=="RED")//case 1:兄弟结点为红
{
x->parent->color="RED";
w->color="BLACK";
rightrotate(x->parent);
w=x->parent->left;
}
else if(w->left->color=="BLACK"&&w->right->color=="BLACK")//case 2:兄弟结点两个儿子为黑
{
if(x->parent->color=="RED")
{
w->color="RED";
x->parent->color="BLACK";
flag=false;
}
else
{
if(x->parent==root)
{
w->color="RED";
flag=false;
}
else
{
w->color="RED";
x=x->parent;
w=x->parent->left;
}
}
}
else if(w->left->color=="RED") //case 3:兄弟结点左儿子为红,右儿子为任意
{
w->color=x->parent->color;
x->parent->color="BLACK";
w->left->color="BLACK";
rightrotate(x->parent);
flag=false;
}
else //case 4:右儿子为红,左儿子为黑。变化后变为
{
w->color="RED";
w->right->color="BLACK";
leftrotate(w);
w=x->parent->left;
}
}
}
template<typename Comparable>
void rbtree<Comparable>::print(MODE mode)
{
if(mode==PRE)
PrePrint(root);
else if(mode==MID)
MidPrint(root);
else if(mode==POST)
PostPrint(root);
else
return;
cout<<endl;
}
template<typename Comparable>
void rbtree<Comparable>::PrePrint(Node<Comparable>* t)
{
if(t==NULL)
return;
else
{
cout<<"("<<t->element<<","<<t->color<<")"<<" ";
PrePrint(t->left);
PrePrint(t->right);
}
}
template<typename Comparable>
void rbtree<Comparable>::MidPrint(Node<Comparable>* t)
{
if(t==NULL)
return;
else
{
MidPrint(t->left);
cout<<"("<<t->element<<","<<t->color<<")"<<" ";
MidPrint(t->right);
}
}
template<typename Comparable>
void rbtree<Comparable>::PostPrint(Node<Comparable>* t)
{
if(t==NULL)
return;
else
{
PostPrint(t->left);
PostPrint(t->right);
cout<<"("<<t->element<<","<<t->color<<")"<<" ";
}
}
template<typename Comparable>
void rbtree<Comparable>::leftrotate(Node<Comparable>* t)//左旋
{
Node<Comparable>* temp=t->right;
t->right=temp->left;
temp->left=t;
if(t!=root)
{
temp->parent=t->parent;
if(t==t->parent->left)
t->parent->left=temp;
else
t->parent->right=temp;
}
else
root=temp;
t->parent=temp;
if(t->right!=NULL)
t->right->parent=t;
}
template<typename Comparable>
void rbtree<Comparable>::rightrotate(Node<Comparable>* t) //右旋
{
Node<Comparable>* temp=t->left;
t->left=temp->right;
temp->right=t;
if(t!=root)
{
temp->parent=t->parent;
if(t==t->parent->right)
t->parent->right=temp;
else
t->parent->left=temp;
}
else
root=temp;
t->parent=temp;
if(t->left!=NULL)
t->left->parent=t;
}
RB_Tree.cpp
// RB_Tree.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include"rb-tree.h"
#include"rb-tree.cpp"
#include<iostream>
#include<string>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
rbtree<int> r;
int a[9]={18,10,20,9,15,19,21,14,16};
for(int i=0;i<9;i++)
r.insert(a[i]);
r.remove(21);
r.print(MID);
return 0;
}