红黑树本质是二叉搜索树,只是它有如下的额外条件
- 每个结点要么为红色要么为黑色;
- 根节点是黑色的 ;
- NULL结点是黑色的;
- 如果一个结点是红色的,那么它的两个子节点都是黑色的;
- 对每个结点,从该结点到其所有后代叶节点的简单路径上,均包含相同数目的黑色结点。
之所以要有如下的额外条件,是为了保证树高为O(lgn)。因为在普通二叉搜索树中,树高为O(n),而不是O(lgn)。
下面给出了结点左旋,结点右旋, 和修复插入所带来的性质破坏,修复删除所带来的性质破坏以及插入代码 和删除代码,其它操作,如查找,遍历,后继和前驱都和普通二叉搜索树一样。
首先,还是要定义结点存储的元素类型,定义如下:
enum {RED,BLACK}
template<class Type>
struct node{
12 Type element;
13 node* parent;
14 node* left;
15 node* right;
16 int color;
17 node(const Type& e=Type(),node* p=0,node* l=0,node* r=0,int c=BLACK):element(e),parent(p),left(l),right(r),color(c){}
18 };
结点左旋:
template<class Type>
void redBlackTree<Type>::leftRotate(node* x)
{
if(x->right==nullNode)
throw runtime_error("the node can't be imposed on the operation of leftRotate");
node* y=x->right;
// the parent of node y is assigned by the parent of node x
y->parent=x->parent;
if(x->parent==nullNode)
root=y;
else if(x==x->parent->left)
x->parent->left=y;
else
x->parent->right=y;
// the right of node x is assigned by the left of node y
x->right=y->left;
if(y->left!=nullNode)
y->left->parent=x;
//the left of node y is assigned by node x
y->left=x;
x->parent=y;
}
结点右旋
template<class Type>
void redBlackTree<Type>::rightRotate(node* x)
{
if(x->left==nullNode)
throw runtime_error("the node can't be imposed on the operation of rightRotate");
node* y=x->left;
// the parent of node y is assigned by the parent of node x
y->parent=x->parent;
if(x->parent==nullNode)
root=y;
else if(x==x->parent->left)
x->parent->left=y;
else
x->parent->right=y;
//the left of node x is assigned by the right of node y
x->left=y->right;
if(y->right!=nullNode)
y->right->parent=x;
//the right of node y is assigned by node x
y->right=x;
x->parent=y;
}
修复插入所带来的性质破坏:
template<class Type>
void redBlackTree<Type>::RBInsertFixup(node* currentNode)
{
while(currentNode->parent->color==RED){
if(currentNode->parent==currentNode->parent->parent->left){
node* uncleNode=currentNode->parent->parent->right;
// 书本中的插入情况1
if(uncleNode->color==RED){
currentNode->parent->color=BLACK;
uncleNode->color=BLACK;
currentNode->parent->parent->color=RED;
currentNode=currentNode->parent->parent;
}
//书本中的插入情况2
else if(currentNode==currentNode->parent->right){
currentNode=currentNode->parent;
leftRotate(currentNode);
}
//书本中的插入情况3
else{
currentNode->parent->color=BLACK;
currentNode->parent->parent->color=RED;
rightRotate(currentNode->parent->parent);
}
}
//与与之匹配的if的情况对称,left换成right,right换成left即可
else {
node* uncleNode=currentNode->parent->parent->left;
if(uncleNode->color==RED){
currentNode->parent->color=BLACK;
uncleNode->color=BLACK;
currentNode->parent->parent->color=RED;
currentNode=currentNode->parent->parent;
}
else if(currentNode==currentNode->parent->left){
currentNode=currentNode->parent;
rightRotate(currentNode);
}
else{
currentNode->parent->color=BLACK;
currentNode->parent->parent->color=RED;
leftRotate(currentNode->parent->parent);
}
}
}
root->color=BLACK;
}
插入:
template<class Type>
bool redBlackTree<Type>::insert(const Type& val)
{
node* parentNode=nullNode;
node* currentNode=root;
//找到要插入的位置;
while(currentNode!=nullNode){
parentNode=currentNode;
if(currentNode->element<val)
currentNode=currentNode->right;
else if(val<currentNode->element)
currentNode=currentNode->left;
else
return false;
}
// 插入该元素并且修复该元素所带来红黑树性质的破坏;
if(parentNode==nullNode)
root=new node(val,nullNode,nullNode,nullNode,BLACK);
else if(val<parentNode->element){
parentNode->left=new node(val,parentNode,nullNode,nullNode,RED);
RBInsertFixup(parentNode->left);
}
else{
parentNode->right=new node(val,parentNode,nullNode,nullNode,RED);
RBInsertFixup(parentNode->right);
}
return true;
}
修复删除所带来的性质破坏
template<class Type>
void redBlackTree<Type>::RBRemoveFixup(node* currentNode)
{
while(currentNode!=root&¤tNode->color==BLACK){
if(currentNode==currentNode->parent->left){
node* uncleNode=currentNode->parent->right;
//书本中的删除情况1
if(uncleNode->color==RED){
uncleNode->color=BLACK;
currentNode->parent->color=RED;
leftRotate(currentNode->parent);
}
//书本中的删除情况2
else if(uncleNode->left->color==BLACK&&uncleNode->right->color==BLACK){
uncleNode->color=RED;
currentNode=currentNode->parent;
}
//书本中的删除情况3
else if(uncleNode->right->color==BLACK){
uncleNode->color=RED;
uncleNode->left->color=BLACK;
rightRotate(uncleNode);
}
//书本中的删除清况4
else{
uncleNode->color=currentNode->parent->color;
uncleNode->right->color=BLACK;
currentNode->parent->color=BLACK;
leftRotate(currentNode->parent);
currentNode=root;
}
}
//与与之匹配的if的情况对称,left与right互换即可。
else{
node* uncleNode=currentNode->parent->left;
if(uncleNode->color==RED){
uncleNode->color=BLACK;
currentNode->parent->color=RED;
rightRotate(currentNode->parent);
}
else if(uncleNode->right->color==BLACK&&uncleNode->left->color==BLACK){
uncleNode->color=RED;
currentNode=currentNode->parent;
}
else if(uncleNode->left->color==BLACK){
uncleNode->color=RED;
uncleNode->right->color=BLACK;
leftRotate(uncleNode);
}
else{
uncleNode->color=currentNode->parent->color;
uncleNode->left->color=BLACK;
currentNode->parent->color=BLACK;
rightRotate(currentNode->parent);
currentNode=root;
}
}
}
currentNode->color=BLACK;
}
删除:
template<class Type>
void redBlackTree<Type>::transplant(node* u,node* v) // node v is to replace node u;
{
if(u->parent==nullNode)
root=v;
else if(u==u->parent->left)
u->parent->left=v;
else
u->parent->right=v;
v->parent=u->parent;
}
template<class Type>
bool redBlackTree<Type>::remove(const Type& val)
{
node* searchNode=search(val,root);//找到要删除的结点
if(searchNode==nullNode)
return false;//要删除的值不存在
node* tmpNode=searchNode;
int tmpNodeOriginalColor=tmpNode->color;
node* nextOfTmpNode=0;
//要删除的结点左边为空
if(searchNode->left==nullNode){
nextOfTmpNode=tmpNode->right;
transplant(searchNode,searchNode->right);
}
//要删除的结点右边为空
else if(searchNode->right==nullNode){
nextOfTmpNode=tmpNode->left;
transplant(searchNode,searchNode->left);
}
//要删除的结点左右均不为空
else{
tmpNode=findMin(searchNode->right);//找到要删除结点的后继结点。
nextOfTmpNode=tmpNode->right;
//用要被删除结点的后继结点取替换它
if(tmpNode->parent==searchNode)
nextOfTmpNode->parent=tmpNode;
else{
transplant(tmpNode,tmpNode->right);
tmpNode->right=searchNode->right;
tmpNode->right->parent=tmpNode;
}
transplant(searchNode,tmpNode);
tmpNode->left=searchNode->left;
tmpNode->color=searchNode->color;
}
//删除结点并且修复删除所带来的红黑树性质的破坏
delete searchNode;
if(tmpNodeOriginalColor==BLACK)
RBRemoveFixup(nextOfTmpNode);
return false;
}