1.红黑树的性质。
1)根节点是黑色。
2)所有节点要么是红色,要么是黑色。
3)红节点的孩子必然是黑色。
4)都用叶子节点结尾,且叶子节点是哨兵,都是黑色,没有实际的key值。
5)每一个节点的所有黑高都是相等的,黑高即是从此节点开始,到每一个哨兵所经历的黑节点的个数。
2.红黑树的插入。
1)插入。与普通二叉查找树没有区别。
2)插入修复。(为了方便,在插入的节点通常都先设为红节点)
case 1:如果插入节点z的父亲p是黑色,那么并不影响红黑色树的任何性质。
case 2:如果插入节点z的父亲p是红色,影响了性质3,这时p的父亲g必然是黑色,那么p的父亲的另外一个孩子u(即是p的叔父节点)的颜色有以下几种情况。
case 2.1:u是红色的,只需要将u,p变成黑色,他们的父亲g变成红色,然后把g赋值给z进行下一轮修复。
case 2.2:u是黑色的,这时看z与p是否都是同侧(即都是左孩子,还是都是右孩子),如果是同侧,可绕g旋转,并且把更改p,g的颜色即可恢复。
case 2.3:u是黑色的,,这时看z与p是否都是同侧(即都是左孩子,还是都是右孩子),如果是异侧,可绕p旋转,并且把z改为旋转后的孩子(即旋转前的父亲),然后变成情况2.2,进行修复。
3.红黑树的删除。
1)删除。正常删除即可,注意记录删除点的孩子移动行踪x,及其删除点z的原始颜色,如果是红色,不影响红黑树的任何性质,否则要进行删除修复。
2)删除修复。(如果修复过程中根节点变红,最终一定要把他变黑)
case 1:如果x是红色,只需要将变成黑色即可恢复性质。
case 2:如果x是黑色,x的兄弟w是红色,那么x的父亲p是黑色,把他变成黑色,并且绕P旋转就可以转换成x的兄弟是w是黑色即case 3。
case 3:如果x是黑色,x的兄弟w是黑色,如果w的其同侧孩子是黑色,异侧孩子也是黑色,把w变成红色,把x与w的父亲作为新的x进行下一轮修复。
case 4:如果x是黑色,x的兄弟w是黑色,如果w的其同侧孩子是黑色,异侧孩子是红色,绕w旋转可以转换成 case 5;
case 5:如果x是黑色,x的兄弟w是黑色,如果w的其同侧孩子是红色,绕x与w的父亲旋转并且相应的变色即可修复。
4.代码
1)RB_Tree.h
//NO Solution Questions:
// The Root Init IS dynamic or Static?
// NIL Node IS Dynamic,How to Get Space?
// can`n use "inline" ,why?
// Don`t Put many numbers Test
/******
Date:2015.3.5
Code is Edit BY LHF
*******/
//---------------------
//---------------------
#ifndef RB_TREE_HHHH
#define RB_TREE_HHHH
#define NULL 0
enum Color
{
Red,
Black
};
typedef struct _node
{
int key;
_node* Left;
_node* Right;
_node* p;
Color color;
}Node;
//typedef struct RB_ree
//{
// int NodeCount;
// Node* Root;
//
//}T;
class Rb_Tree
{
public:
Rb_Tree()
{
NIL.color=Black;
NIL.Left=NULL;
NIL.Right=NULL;
NIL.p=NULL;
NIL.key=-10000;
Root =new Node();
//Node r,a,b;
(*Root).color=Black;
(*Root).key=2;
(*Root).Left=new Node();
(*Root).Right=new Node();
(*Root).p=NULL;
*(*Root).Left=*(*Root).Right=NIL;
(*Root).Left->p=Root;
(*Root).Right->p=Root;
//Root=&r;
};
Rb_Tree(Node* _root)
{
Root=_root;
//NIL=new Node();
NIL.color=Black;
NIL.Left=NULL;
NIL.Right=NULL;
NIL.p=NULL;
NIL.key=-10000;
};
void LeftLoate(Node* node);
void RightLoate(Node* node);
void RB_Insert(Node* z);
void RB_Insert_Fixup(Node* z);
void RB_TransPlant(Node* u,Node* v);
void RB_Delete(Node* z);
void RB_Delete_Fixup(Node* x);
Node* Tree_Min(Node* node);
Node* SearchNode(int key);
void PintTree()
{
PintNode(Root);
};
~Rb_Tree()
{
//delete Root;
};
private:
void PintNode(Node* node);
int NodeCount;
Node* Root;
Node NIL;
};
#endif
2)RB_Tree.cpp
#include"RB-TREE.h"
#include<iostream>
using namespace std;
bool operator == (Node a,Node b)
{
if(a.key!=b.key)
return 0;
/*if(a.Left!=b.Left)
return 0;
if(a.Right!=b.Right)
return 0;*/
if(a.color!=b.color)
return 0;
return 1;
/*if(a.p!=b.p)
return 0;*/
}
bool operator != (Node a,Node b)
{
return !(a==b);
}
void Rb_Tree::PintNode(Node* node)
{
if(*node!=NIL)
{
cout<<node->key<<":"<<node->color<<" ";
PintNode(node->Left);
PintNode(node->Right);
}
else
{
cout<<endl;
}
}
Node* Rb_Tree::SearchNode(int key)
{
Node *temp=Root;
while (*temp!=NIL)
{
if(temp->key<key)
{
temp=temp->Right;
}
else if(temp->key>key)
{
temp=temp->Left;
}
else
{
return temp;
}
}
return NULL;
};
void Rb_Tree::LeftLoate(Node* node)
{
Node* y=node->Right;
//if(y->Left!=NULL)
{
node->Right=y->Left;
}
y->Left=node;
y->p=node->p;
if(node->p!=NULL)
{
if(node==node->p->Right)
{
node->p->Right=y;
}
else
{
node->p->Left=y;
}
}
node->p=y;
}
void Rb_Tree::RightLoate(Node* node)
{
Node* y=node->Left;
//if(*(y->Right)!=Rb_Tree::NIL)
{
node->Left=y->Right;
}
y->Right=node;
y->p=node->p;
if(node->p!=NULL)
{
if(node==node->p->Right)
{
node->p->Right=y;
}
else
{
node->p->Left=y;
}
}
node->p=y;
}
void Rb_Tree::RB_Insert(Node* z)
{
Node* y=NULL;
/*int a=5;
int c=6;
int * const b=&a;
*b=c;
int*c =b;*/
Node* x=Rb_Tree::Root;
while (*x!=Rb_Tree::NIL)
{
y=x;
if(z->key<x->key)
{
x=x->Left;
}
else
{
x=x->Right;
}
}
z->p=y;
if(y==NULL)
{
Root=z;
}
else if(z->key<y->key)
{
y->Left=z;
}
else
{
y->Right=z;
}
z->Left=new Node(NIL);
z->Left->p=z;
z->Right=new Node(NIL);
z->Right->p=z;
z->color=Red;
RB_Insert_Fixup(z);
//delete y;
}
void Rb_Tree::RB_Insert_Fixup(Node* z)
{
while (z->p!=NULL&&z->p->color==Red)
{
if(z->p==z->p->p->Right)
{
if(z->p->p->Left->color==Red)
{
z->p->color=Black;
z->p->p->Left->color=Black;
z->p->p->color=Red;
z=z->p->p;
continue;
}
if(z==z->p->Left)
{
z=z->p;
RightLoate(z);
//z=z->Left;
}
z->p->color=Black;
z->p->p->color=Red;
LeftLoate(z->p->p);
}
else
{
if(z->p->p->Right->color==Red)
{
z->p->color=Black;
z->p->p->Right->color=Black;
z->p->p->color=Red;
z=z->p->p;
continue;
}
if(z==z->p->Right)
{
z=z->p;
LeftLoate(z);
//z=z->Left;
}
z->p->color=Black;
z->p->p->color=Red;
RightLoate(z->p->p);
}
}
Root->color=Black;
}
void Rb_Tree::RB_TransPlant(Node* u,Node* v)
{
if(u->p==NULL)
{
Root=v;
}
else if(u==u->p->Left)
{
u->p->Left=v;
}
else
{
u->p->Right=v;
}
v->p=u->p;
}
void Rb_Tree::RB_Delete(Node* z)
{
Node* x=NULL;
Node* y=z;
Color y_orginal_color=z->color;
if(*(z->Left)==NIL)
{
x=z->Right;
RB_TransPlant(z,z->Right);
}
else if(*(z->Right)==NIL)
{
x=z->Left;
RB_TransPlant(z,z->Left);
}
else
{
y=Tree_Min(z->Right);
x=y->Right;
y_orginal_color=y->color;
if(y->p==z)
{
x->p=y;
}
else
{
RB_TransPlant(y,y->Right);
y->Right=z->Right;
z->Right->p=y;
}
RB_TransPlant(z,y);
y->color=z->color;
y->Left=z->Left;
y->Left->p=y;
}
if(y_orginal_color==Black)
{
RB_Delete_Fixup(x);
}
/*if(z->Left->p==z&&*(z->Left)==NIL)
{
}*/
//delete x;
}
void Rb_Tree::RB_Delete_Fixup(Node* x)
{
while (x->color==Black&&*(x->p)!=NIL)
{
if(x==x->p->Left)
{
if(x->p->Right->color==Red)
{
x->p->color=Red;
x->p->Right->color=Black;//case 1
LeftLoate(x->p);
}
if(x->p->Right->Right->color==Black&&x->p->Right->Left->color==Black)//case 2
{
x->p->Right->color=Red;
x=x->p;
continue;
}
if(x->p->Right->Right->color==Black&&x->p->Right->Left->color==Red)//case 3
{
x->p->Right->color=Red;
x->p->Right->Left->color=Black;
RightLoate(x->p->Right);
}
x->p->Right->color=x->p->color;
x->p->color=Black;
x->p->Right->Right->color=Black;
LeftLoate(x->p);
break;
}
else
{
if(x->p->Left->color==Red)
{
x->p->color=Red;
x->p->Left->color=Black;//case 1
RightLoate(x->p);
}
if(x->p->Left->Left->color==Black&&x->p->Left->Right->color==Black)//case 2
{
x->p->Left->color=Red;
x=x->p;
continue;
}
if(x->p->Left->Left->color==Black&&x->p->Left->Right->color==Red)//case 3
{
x->p->Left->color=Red;
x->p->Left->Right->color=Black;
LeftLoate(x->p->Left);
}
x->p->Left->color=x->p->color;
x->p->color=Black;
x->p->Left->Left->color=Black;
RightLoate(x->p);
break;
}
}
x->color=Black;
}
Node* Rb_Tree::Tree_Min(Node* node)
{
while (*(node->Left)!=NIL)
{
node=node->Left;
}
return node;
}