1、红黑树是二叉收索树的一种,可以保证在最坏情况系基本动态集合操作的时间复杂度为O(lgn)。本质是让树尽量均衡。
红黑树的定义(红黑树是在二叉收索树的基础上加上了下面的条件):
(1)每个节点或是红色的,或是黑色的。
(2)根节点和叶结点是黑色的。(红黑树中将NIL结点定义为也节点,称为外部结点;把带关键字的结点视为树的内部结点)。
(3)如果一个结点是红色的,则它的两个子结点是黑色的(父结点也是黑色的)。
(4)对每个结点,从该结点到其所有后代叶结点的简单路径上,均包括相同数目的黑色结点。(不含该结点的黑结点的数目称为黑高)
2、引理:一颗有n个内部结点的红黑树的高度至多为2lg(n+1)。
证明:
3、代码的实现:
R_B_tree.h
#ifndef __RedBlackTree
#define __RedBlackTree
#include<iostream>
#include<queue>
using namespace std;
typedef enum NodeColor{
RED,
BLACK
}NodeColor;
typedef struct Node{
NodeColor color;
int key;
Node *left;
Node *right;
Node *parent;
}Node;
class RedBlackTree{
public:
RedBlackTree(); //空树
~RedBlackTree();
Node *Search(int key); //根据关键字key从根部查询节点,将节点返回
Node *Minimum(Node *x); //以x为根的红黑树的最小值
Node *Maximum(Node *x); //以x为根的红黑树的最大值
Node *Successor(Node *node); //后继
Node *Predecessor(Node *node); //前驱
void InsertNode(Node *node); //将node结点插入root树
void InorderTreeWalk(Node *x); //中序遍历
void DelleteNode(Node *z); //删除节点
private:
void LeftRotate(Node *x); //按x点左旋
void RightRotate(Node *y); //按y点右旋
void InsertFixup(Node *z); //插入节点后从新着色
void Transplant(Node *u,Node *v); //用v节点为根的子树替换u节点为根的子树
void DelleteFixup(Node *z); //删除节点之后重新着色
private:
Node leaf; //哨兵结点
public:
Node *root; //树根
};
#else
#pragma message("--RedBlackTree已编译。")
#endif
R_B_tree.cpp
#include"R_B_tree.h"
RedBlackTree::RedBlackTree(){
this->leaf.color=BLACK;
this->leaf.key=0;
this->leaf.left=NULL;
this->leaf.parent=NULL;
this->leaf.right=NULL;
root=&leaf; //空红黑树
}
RedBlackTree::~RedBlackTree(){
}
Node * RedBlackTree::Minimum(Node *x){
if( x==&leaf ){ //x为叶子
return x;
}
while( x->left != &leaf ){
x=x->left;
}
return x; //最小
}
Node * RedBlackTree::Maximum(Node *x){
if( x==&leaf ){ //x为叶子
return x;
}
while( x->right != &leaf ){
x=x->right;
}
return x; //最大
}
Node * RedBlackTree::Successor(Node *node){
if(node==&leaf) return node;
return Minimum(node->right);
}
Node * RedBlackTree::Predecessor(Node *node){
if(node==&leaf) return node;
return Maximum(node->left);
}
Node * RedBlackTree::Search(int key){
Node *x;
x=root;
while( x != &leaf && x->key != key ){
if( x->key > key )x=x->left;
else if(x->key < key) x=x->right;
}
return x; //查询失败是返回叶子结点
}
void RedBlackTree::LeftRotate(Node *x){
Node *y;
y=x->right;
x->right=y->left;
if( y->left != &leaf ){
y->left->parent=x;
}
y->parent=x->parent;
if( x->parent == &leaf ){ //x为根
root=y;
}else{
if( x == x->parent->left ){ //x为父结点的左孩子
x->parent->left=y;
}else{ //x为右孩子
x->parent->right=y;
}
}
y->left=x;
x->parent=y;
}
void RedBlackTree::RightRotate(Node *y){
Node *x;
x=y->left;
y->left=x->right;
if( x->right != &leaf){
x->right->parent=y;
}
x->parent=y->parent;
if( y->parent == &leaf ){
root=x;
}else{
if( y->parent->left==y ){ //左边第一个结点
y->parent->left=x;
}else{
y->parent->right=x; //右边第一个结点
}
}
x->right=y;
y->parent=x;
}
void RedBlackTree::InsertFixup(Node *z){
Node *y;
while( z->parent->color == RED ){
if( z->parent==z->parent->parent->left ){
y=z->parent->parent->right; //叔结点
if( y->color==RED ){ //情况一
z->parent->color=BLACK;
y->color=BLACK;
z->parent->parent->color=RED;
z=z->parent->parent;
}else{
if( z->parent->right == z ){ //情况二 右孩子
z=z->parent;
this->LeftRotate(z);
}
z->parent->color=BLACK; //情况三 左孩子
z->parent->parent->color=RED;
this->RightRotate(z->parent->parent);
}
}else{
y=z->parent->parent->left; //叔结点
if( y->color==RED ){ //情况一
z->parent->color=BLACK;
y->color=BLACK;
z->parent->parent->color=RED;
z=z->parent->parent;
}else{
if( z->parent->left == z ){ //情况二 左孩子
z=z->parent;
this->RightRotate(z);
}
z->parent->color=BLACK; //情况三 左孩子
z->parent->parent->color=RED;
this->LeftRotate(z->parent->parent);
}
}
}
root->color=BLACK;
}
void RedBlackTree::InsertNode(Node *node){
Node *y,*x;
y=&leaf;x=root;
while( x!=&leaf ){
y=x;
if( node->key < x->key ){
x=x->left;
}else{
x=x->right;
}
}
node->parent=y;
if( y == &leaf ){
root=node;
}else{
if(node->key<y->key){
y->left=node;
}else{
y->right=node;
}
}
node->left=&leaf;
node->right=&leaf;
node->color=RED;
this->InsertFixup(node);
}
void RedBlackTree::InorderTreeWalk(Node *x){
if( x != &leaf ){
InorderTreeWalk(x->left);
cout<<"key="<<x->key;
if( x->color==RED ){
cout<<" RED";
}else{
cout<<" BLACK";
}
cout<<" parent_ket="<<x->parent->key<<" key_left="<<x->left->key<<" key_right="<<x->right->key<<endl;
InorderTreeWalk(x->right);
}
}
void RedBlackTree::Transplant(Node *u,Node *v){
if(u->parent==&leaf){
root=v;
}else{
if( u==u->parent->left ){
u->parent->left=v;
}else{
u->parent->right=v;
}
}
v->parent=u->parent;
}
void RedBlackTree::DelleteFixup(Node *z){
Node *w;
while( z!=root && z->color == BLACK ){
if( z==z->parent->left ){
w=z->parent->right;
if( w->color==RED ){
w->color=BLACK;
z->parent->color=RED;
this->LeftRotate(z->parent);
w=z->parent->right;
}
if( w->left->color==BLACK && w->right->color==BLACK){
w->color=RED;
z=z->parent;
}else{
if( w->right->color==BLACK ){
w->left->color=BLACK;
w->color=RED;
this->RightRotate(w);
w=z->parent->right;
}
w->color=z->parent->color;
z->parent->color=BLACK;
w->right->color=BLACK;
this->LeftRotate(z->parent);
z=root;
}
}else{
w=z->parent->left;
if( w->color==RED ){
w->color=BLACK;
z->parent->color=RED;
this->RightRotate(z->parent);
w=z->parent->left;
}
if( w->left->color==BLACK && w->right->color==BLACK){
w->color=RED;
z=z->parent;
}else{
if( w->left->color==BLACK ){
w->right->color=BLACK;
w->color=RED;
this->LeftRotate(w);
w=z->parent->left;
}
w->color=z->parent->color;
z->parent->color=BLACK;
w->left->color=BLACK;
this->RightRotate(z->parent);
z=root;
}
}
}
z->color=BLACK;
}
void RedBlackTree::DelleteNode(Node *z){
Node *x,*y;
NodeColor y_original_color;
y=z;
y_original_color=y->color;
if( z->left==&leaf ){
x=z->right;
Transplant(z,z->right);
}else{
if(z->right==&leaf){
x=z->left;
Transplant(z,z->right);
}else{
y=Minimum(z->right);
y_original_color=y->color;
x=y->right;
if( y->parent==z ){
x->parent=y;
}else{
Transplant(y,y->right);
y->right=z->right;
y->right->parent=y;
}
Transplant(z,y);
y->left=z->left;
y->left->parent=y;
y->color=z->color;
}
}
if(y_original_color==BLACK){
DelleteFixup(x);
}
delete z;
}
main.cpp
#include<ctime>
#include"R_B_tree.h"
int main(){
Node *newNode;
RedBlackTree RB;
int i=4;
srand(time(0));
int kk;
while(i<11){
//kk=rand()%10+5;
newNode=new Node;
newNode->color=RED;
newNode->key=i;
newNode->left=NULL;
newNode->right=NULL;
newNode->parent=NULL;
RB.InsertNode(newNode);
i++;
}
cout<<"创建的红黑树"<<endl;
RB.InorderTreeWalk((RB.root));
if( RB.Search(RB.root->key)->key==0 ){
cout<<"查询的结点不存在!"<<endl;
}else{
cout<<"查询的根节点结点为 "<<RB.Search(RB.root->key)->key<<endl;
}
RB.DelleteNode((RB.root));
cout<<"删除根节点之后的红黑树 "<<endl;
RB.InorderTreeWalk((RB.root));
if( RB.Search(RB.root->key)->key==0 ){
cout<<"查询的结点不存在!"<<endl;
}else{
cout<<"查询的根节点结点为 "<<RB.Search(RB.root->key)->key<<endl;
}
int asd;
cin>>asd;
return 0;
}
运行截图:
4、关于红黑树删除的一些说明
红黑树所有操作里,结点的删除是最复杂的,相关的删除的操作的详细过程可以看http://www.cnblogs.com/Anker/archive/2013/01/30/2882773.html博客,写的不错,看过之后容易明白。在这里我在添加关于4种情况的实例,从而可以更好理解红黑树删除时的四种情况。