在算法导论中看了红黑树,没事儿就实现了一下,代码贴在下面。
#include <iostream>
using namespace std;
const int black = 1;
const int red = -1;
typedef struct node
{
struct node* parent;
struct node* lchild;
struct node* rchild;
int color;
int data;
}node,*pnode;
typedef struct tree{
node *root;
}tree;
node NIL={NULL,NULL,NULL,black,1943};//哨兵节点,1943是我的幸运数字哈,哨兵节点默认为黑色,树种用NIL代替null
void right_rotate(tree *t,node *x)//right_rotate
{
if(x!=t->root){
node* y = x->lchild;
node* p = x->parent;
if(x==p->lchild)
{
y->parent = p;
p->lchild = y;
x->parent = y;
x->lchild = y->rchild;
y->rchild->parent = x;
y->rchild = x;
}else{
y->parent = p;
p->rchild = y;
x->parent = y;
x->lchild = y->rchild;
y->rchild->parent = x;
y->rchild = x;
}
}else{
node* y = x->lchild;
x->lchild = y->rchild;
y->rchild->parent = x;
y->parent = x->parent;
x->parent = y;
y->rchild = x;
t->root = y;
}
}
void left_rotate(tree* t,node * x)//left_rotate
{
if(x!=t->root){
node* y = x->rchild;
node* p = x->parent;
if(x==p->lchild)
{
y->parent = p;
p->lchild = y;
x->parent = y;
x->rchild = y->lchild;
y->lchild->parent = x;
y->lchild = x;
}else{
y->parent = p;
p->rchild = y;
x->parent = y;
x->rchild = y->lchild;
y->lchild->parent = x;
y->lchild = x;
}
}else{
node* y = x->rchild;
x->rchild = y->lchild;
y->lchild->parent = x;
y->parent = x->parent;
x->parent = y;
y->lchild = x;
t->root = y;
}
}
void rb_insert_fixup(tree* t,node* n);//插入节点之后重新调整为红黑树调整为
void rb_insert(tree* t,node *n)//插入节点
{
node* parent = t->root;
node* p = parent;
n->color = red;
bool isLeft = false;
while(p!=&NIL)
{
parent = p;
if(p->data>n->data)
{
p = p->lchild;
isLeft = true;
}else{
p = p->rchild;
isLeft = false;
}
}
if(isLeft)//插入节点为左儿子
{
parent->lchild = n;
n->parent = parent;
}else//插入节点为右儿子
{
parent->rchild = n;
n->parent = parent;
}
if(parent->color==red)
rb_insert_fixup(t,n);
t->root->color = black;
}
void rb_insert_fixup(tree* t,node* n)
{
node* p = n;
while(p!=t->root&&p->parent!=t->root&&p!=&NIL)
{
if(p->parent==p->parent->parent->rchild)//插入节点的父是插入节点祖父的右儿子
{
if(p->parent->parent->lchild->color==red)//插入节点的叔叔是红色的
{
p->parent->color = black;
p->parent->parent->lchild->color=black;
p->parent->parent->color = red;
p = p->parent->parent;
continue;
}else//插入节点的叔叔是黑色的
{
if(p==p->parent->lchild)
{
right_rotate(t,p->parent);
left_rotate(t,p->parent);
p->color = black;
p->lchild->color = red;
break;
}else
{
left_rotate(t,p->parent->parent);
p->parent->color = black;
p->parent->lchild->color = red;
break;
}
}
}else//插入节点的父是插入节点祖父的左儿子
{
if(p->parent->parent->rchild->color==red)
{
p->parent->color = black;
p->parent->parent->rchild->color=black;
p->parent->parent->color = red;
p = p->parent->parent;
continue;
}else
{
if(p==p->parent->rchild)
{
left_rotate(t,p->parent);
right_rotate(t,p->parent);
p->color = black;
p->rchild->color = black;
break;
}else
{
right_rotate(t,p->parent->parent);
p->parent->color = black;
p->parent->rchild->color = red;
break;
}
}
}
}
}
node* tree_successor(tree* t,node* n)//取节点n的后继节点
{
node* p = n->rchild;
node* parent = p;
while(p!=&NIL)
{
parent = p;
p = p->lchild;
}
return parent;
}
void rb_delete_fixup(tree* t,node* n);
node* rb_delete(tree* t,node* n)//删除节点
{
node* p = t->root;
node* parent = p;
node* d = &NIL;
node* replc = &NIL;
bool isLeft = false;
while(p!=&NIL)//找到n的位置,以防删除不存在节点
{
parent = p;
if(p->data>n->data)
{
p = p->lchild;
isLeft = true;
}else{
if(p->data<n->data)
{
p = p->rchild;
isLeft = false;
}else
{
break;
}
}
}
if(p==&NIL)
{
cout<<"element not exist"<<endl;
return p;
}
if(n->lchild==&NIL||n->rchild==&NIL)//若n没有两个儿子
{
d = n;
}else//n有两个宝贝儿子
{
d = tree_successor(t,n);//则删除他丫的后继,把n的值与后继的值对调,但是颜色不改变
}
if(d->lchild!=&NIL)//如果没有两个儿子则用其中一个儿子顶替父亲,(没有儿子则用右边的NIL节点顶上,NIL是一个哨兵节点)
{
replc = d->lchild;
}else{
replc = d->rchild;
}
replc->parent = d->parent;
if(d->parent->lchild == d)
{
d->parent->lchild = replc;
}else{
d->parent->rchild = replc;
}
if(d!=n)
{
int temp = d->data;
d->data = n->data;
n->data = temp;
}
if(d->color==black)
{
rb_delete_fixup(t,replc);
}
d->lchild = &NIL;
d->rchild = &NIL;
d->parent = &NIL;
return d;
}
void rb_delete_fixup(tree* t,node* n)//删除后如果有双黑节点则要重新调整树为红黑树
{
node* p = n;
while(p!=t->root)
{
if(p==p->parent->lchild)//双黑p是左儿子
{
if(p->parent->rchild->color == red)//p的兄弟是红色的
{
int temp = p->parent->color;
p->parent->color = p->parent->rchild->color;
p->parent->rchild->color = temp;
left_rotate(t,p->parent);
p->color = black;
}else{
if(p->parent->rchild->rchild->color==red)//p的远侄是红色的
{
p->parent->rchild->color = p->parent->color;
p->parent->color = black;
p->parent->rchild->rchild->color = black;
left_rotate(t,p->parent);
break;
}else{
if(p->parent->rchild->lchild->color==red)//p的近侄是红色的
{
right_rotate(t,p->parent->rchild);
p->parent->rchild->color = p->parent->color;
p->parent->color = black;
left_rotate(t,p->parent);
}else{//两个侄子都是黑色的
p->parent->rchild->color = red;
if(p->parent->color == red)
{
p->parent->color = black;
break;
}
p->color = black;
p = p->parent;
}
}
}
}else{//p是右儿子
if(p->parent->lchild->color == red)
{
int temp = p->parent->color;
p->parent->color = p->parent->lchild->color;
p->parent->lchild->color = temp;
right_rotate(t,p->parent);
p->color = black;
}else{
if(p->parent->lchild->rchild->color==red)
{
p->parent->lchild->color = p->parent->color;
p->parent->color = black;
p->parent->lchild->lchild->color = black;
right_rotate(t,p->parent);
break;
}else{
if(p->parent->lchild->rchild->color==red)
{
left_rotate(t,p->parent->rchild);
p->parent->lchild->color = p->parent->color;
p->parent->color = black;
right_rotate(t,p->parent);
}else{
p->parent->lchild->color = red;
if(p->parent->color == red)
{
p->parent->color = black;
break;
}
p->color = black;
p = p->parent;
}
}
}
}
}
p->color = black;//最后双黑p调整为普通黑色
}
void printTree(node* n)//先序遍历输出。
{
if(n!=&NIL)
{
cout<<n->data<<" - "<<n->color<<endl;
printTree(n->lchild);
printTree(n->rchild);
}
return;
}
int main()//简单测试了,没有问题。若错了,欢迎拍砖。=。=
{
tree t;
node ROOT={&NIL,&NIL,&NIL,black,5};
node n1 = {&NIL,&NIL,&NIL,red,1};
node n4 = {&NIL,&NIL,&NIL,red,4};
node n7 = {&NIL,&NIL,&NIL,red,7};
node n3 = {&NIL,&NIL,&NIL,red,3};
node n6 = {&NIL,&NIL,&NIL,red,6};
node n2 = {&NIL,&NIL,&NIL,red,2};
node n8 = {&NIL,&NIL,&NIL,red,8};
node n9 = {&NIL,&NIL,&NIL,red,9};
t.root = &ROOT;
rb_insert(&t,&n4);
rb_insert(&t,&n3);
rb_insert(&t,&n2);
rb_insert(&t,&n1);
rb_insert(&t,&n6);
rb_insert(&t,&n7);
rb_insert(&t,&n8);
rb_insert(&t,&n9);
rb_delete(&t,&ROOT);
printTree(t.root);
return 0;
}