红黑树(Red Black Tree) 是一种自平衡二叉查找树,是在计算机科学中用到的一种数据结构,典型的用途是实现关联数组。
红黑树的五条性质:(特别重要)
1.节点是红色或黑色
2.根节点是黑色
3. 每个叶节点(NIL节点,空节点)是黑色的,又称为外节点
4.如果一个节点是红色的,则他的两个子节点都是黑色的
5.对每个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点
注意:叶节点,也即外节点,本身没有任何信息,只是标示节点的终结,所以,其key域没有任何意义,但其color域为黑色。(这个规定使得删除内节点操作变得简单便利)
首先定义红黑树类以及其成员方法:
#ifndef RBT_H_20150408
#define RBT_H_20150408
#include<vector>
using std::vector;
class RBT{
struct Node{
Node();
Node(int,bool,Node*,Node*,Node*);
int value;
bool isBlack;
Node *left;
Node *right;
Node *father;
};
Node *root;
Node *NIL;
void left_roll(Node *);
void right_roll(Node *);
void in_fixup(Node *);
void de_fixup(Node *);
public:
RBT();
RBT(vector<int>);
~RBT();
Node *getroot()const;
void insert(int);
void DelEle(Node*,int );
void RBdelete(Node *);
Node *Tree_Successor(Node *);
};
#endif
成员方法的实现
#include<iostream>
#include<vector>
#include "RBT.h"
using namespace std;
RBT::Node::Node():value(-1),isBlack(true),left(NULL),right(NULL),father(NULL){}
RBT::Node::Node(int v,bool isBlack,Node* left,Node* right,Node* father):value(v),isBlack(isBlack),left(left),right(right),father(father){}
RBT::RBT(){
NIL=new Node();
root=NIL;
}
RBT::RBT(vector<int> ivec){
NIL=new Node();
root=NIL;
for(size_t i=0;i<ivec.size();++i)
insert(ivec.at(i));
}
RBT::~RBT(){}
void RBT::left_roll(Node *x){
if(x==NIL||x->right==NIL)
return;
Node *y=x->right;
x->right=y->left;
if(y->left!=NIL)
y->left->father=x;
y->father=x->father;
if(root==x)
root=y;
else if(x==x->father->left)
x->father->left=y;
else
x->father->right=y;
y->left=x;
x->father=y;
}
void RBT::right_roll(Node *x){
if(x==NIL||x->left==NIL)
return;
Node *y=x->left;
x->left=y->right;
if(y->right!=NIL)
y->right->father=x;
y->father=x->father;
if(root==x)
root=y;
else if(x==x->father->left)
x->father->left=y;
else
x->father->right=y;
y->right=x;
x->father=y;
}
void RBT::insert(int v){
Node *y=NIL;
Node *x=root;
Node *newNode=new Node(v,false,NIL,NIL,NIL);
/*if(root==NIL){
root=x;
newNode->isBlack=true;
return;
}*/
while(x!=NIL){
y=x;
if(v<x->value)
x=x->left;
else
x=x->right;
}
newNode->father=y;
if(y==NIL){
root=newNode;
}else if(v<y->value){
y->left=newNode;
}else{
y->right=newNode;
}
in_fixup(newNode);
}
void RBT::in_fixup(Node *z){
Node *y=NIL;
while(z->father!=NIL&&z->father->father!=NIL&&z->father->isBlack==false){//父节点是红色
if(z->father==z->father->father->left){
y=z->father->father->right;//叔叔
if(y!=NIL&&y->isBlack==false){//case 1,uncle is red;
z->father->isBlack=true;
y->isBlack=true;
z->father->father->isBlack=false;
z=z->father->father;
}else{
if(z->father->right==z){//case 2:z as right child
z=z->father;
left_roll(z);
}
z->father->isBlack=true;//case 3:
z->father->father->isBlack=false;
right_roll(z->father->father);
}
}else{
y=z->father->father->left;
if(y!=NIL&&y->isBlack==false){
z->father->isBlack=true;
y->isBlack=true;
z->father->father->isBlack=false;
z=z->father->father;
}else{
if(z->father->left==z){
z=z->father;
right_roll(z);
}
z->father->isBlack=true;
z->father->father->isBlack=false;
left_roll(z->father->father);
}
}
}
root->isBlack=true;
}
RBT::Node* RBT::Tree_Successor(Node *p){
Node *x,*left;
if(p->right!=NIL){
x=p->right;
while((left=x->left)!=NIL)
x=left;
}
return x;
}
void RBT::DelEle(Node *root,int data){
if(root==NULL){
cout<<"Empty tree";
return;
}
if(root->value==data)
RBdelete(root);
else if(data<root->value)
DelEle(root->left,data);
else
DelEle(root->right,data);
}
void RBT::RBdelete(Node *z){
Node *y=NIL;
Node *x=NIL;
//问题转换为删除只有一个孩子的节点(或没有孩子)
if(z->left==NIL||z->right==NIL){
y=z;
}else{
y=Tree_Successor(z);
}
//以上找出要删除的节点
if(y->left!=NIL)
x=y->left;
else
x=y->right;//主要基于Tree_Successor(z)的方式,有两种:先右然后左到底;先左右到底
x->father=y->father;//
if(y==root)
root=x;
else if(y==y->father->left)
y->father->left=x;
else
y->father->right=x;
if(z!=y)
z->value=y->value;
if(y->isBlack==true)//
de_fixup(x);
delete y;
}
void RBT::de_fixup(Node *x){
Node *w=NIL;
while(x!=root&&x->isBlack==true){
if(x==x->father->left){
w=x->father->right;
if(w->isBlack==false){
w->isBlack=true;
x->father->isBlack=false;
left_roll(x->father);
w=x->father->right;
}
if(w->left->isBlack==true&&w->right->isBlack==true){
w->isBlack=false;
x=x->father;
}else{
if(w->right->isBlack==true){
w->left->isBlack=true;
w->isBlack=false;
right_roll(w);
w=x->father->right;
}
w->isBlack=x->father->isBlack;
x->father->isBlack=true;
w->right->isBlack=true;
left_roll(x->father);
x=root;
}
}else{
w=x->father->left;
if(w->isBlack==false){
w->isBlack=true;
x->father->isBlack=false;
right_roll(x->father);
w=x->father->left;
}
if(w->left->isBlack==true&&w->right->isBlack==true){
w->isBlack=false;
x=x->father;
}else{
if(w->left->isBlack==true){
w->right->isBlack=true;
w->isBlack=false;
left_roll(w);
w=x->father->right;
}
w->isBlack=x->father->isBlack;
x->father->isBlack=true;
w->left->isBlack=true;
right_roll(x->father);
x=root;
}
}
}
x->isBlack=true;
}
RBT::Node* RBT::getroot()const{
return root;
}
#include<iostream>
#include<vector>
#include"RBT.h"
using namespace std;
int main(){
vector<int> ivec;
RBT myrbt;
int a[]={11,7,1,2,5,4,8,14,15};
//int a[]={2,11,14,7,15,5,8,4};
/*for(int i=0;i<8;i++)
ivec.push_back(a[i]);*/
for(int i=0;i<9;i++)
myrbt.insert(a[i]);
myrbt.DelEle(myrbt.getroot(),1);
myrbt.getroot();
return 0;
}
最近时间有限,暂时就这么多吧,对于插入和删除操作没有作任何描述……对于红黑树来说,这两个操作还是比较麻烦的(涉及到完成操作后对树的调整)。以后会将删除和插入操作详细讲解一下。