一棵二叉查找树如果满足下面的红黑性质,则为一棵红黑树:
1)每个结点或是红的,或是黑的。
2)根结点是黑的。
3)每个叶子结点(nil)是黑的。
4)如果一个结点是红的,则他的两个儿子都是黑的。
5)对于每个结点,从该结点到其子孙结点(叶子结点)的所有路径包含的相同数目的黑结点。
由于所有的叶子结点都是黑色,所以我们可以用一个结点nil来统一代表所有的叶子结点。
先定义2个结构体。
struct Node
{
Node *left,*right,*p;//左儿子 右儿子 父亲
int key;
int color;//0 red 1 black (2 NIL)
Node()
{
key=color=-1;
left=right=p=NULL;
}
Node(int k)
{
key=k;
color=0;
left=right=p=NULL;
}
};
struct Tree
{
Node *root,*nil;
Tree()
{
nil=new Node();
nil->color=1;
nil->p=nil;
root=nil;
root->p=root;
}
};
插入:
插入结点z,并且把结点z着为红色。
void Insert(Tree *T,Node *z)
{
Node *y=T->nil;
Node *x=T->root;
while(x!=T->nil)
{
y=x;
if((z->key)<(x->key))
x=x->left;
else
x=x->right;
}
z->p=y;
if(y==T->nil)
T->root=z;
else
if((z->key)<(y->key))
y->left=z;
else
y->right=z;
z->left=T->nil;
z->right=T->nil;
z->color=0;//red
Insert_Fixup(T,z);
}
插入过程中可能会破坏红黑树的某些性质。
由于插入的节点颜色是红色,所以破坏的性质要么是性质2,要么是性质4。
a)结点z是红色,且z是根结点。 直接把z的颜色改为黑色。
b)如果p【z】是黑色。 不做变化。
c)如果p【z】是红色。
case1:z的叔叔是红色。 把z的叔叔和z的父亲变为黑色(维持4属性),z的爷爷变为红色(维持5属性)。
case2:z的叔叔是黑色,z是右孩子。
case3:z的叔叔是黑色,z是左孩子。(case2 和 case 3相近)
给出前后变化:
变化后:
这段画画图看看代码就好理解
void Insert_Fixup(Tree *T,Node *z)
{
while(z->p->color==0)//仅仅当case 1的时候while可执行多次
{
if(z->p==z->p->p->left)
{
Node *y=z->p->p->right;
if(y->color==0)//case 1
{
z->p->color=1;
y->color=1;
z->p->p->color=0;
z=z->p->p;
}
else
{
if(z==z->p->right)
{
z=z->p;
Left_Rotate(T,z);
}
z->p->color=1;
z->p->p->color=0;
Right_Rotate(T,z->p->p);
}
}
else//下面么这段代码是跟上面的那段代码left和right交换得到的
{
Node *y=z->p->p->left;
if(y->color==0)
{
z->p->color=1;
y->color=1;
z->p->p->color=0;
z=z->p->p;
}
else
{
if(z==z->p->left)
{
z=z->p;
Right_Rotate(T,z);
}
z->p->color=1;
z->p->p->color=0;
Left_Rotate(T,z->p->p);
}
}
}
T->root->color=1;
}
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
struct Node
{
Node *left,*right,*p;//左儿子 右儿子 父亲
int key;
int color;//0 red 1 black (2 NIL)
Node()
{
key=color=-1;
left=right=p=NULL;
}
Node(int k)
{
key=k;
color=0;
left=right=p=NULL;
}
};
struct Tree
{
Node *root,*nil;
Tree()
{
nil=new Node();
nil->color=1;
nil->p=nil;
root=nil;
root->p=root;
}
};
void Left_Rotate(Tree *T,Node* x)
{
Node *y=x->right;
x->right=y->left;
if(y->left!=T->nil)
y->left->p=x;
y->p=x->p;
if(x->p==T->nil)
T->root=y;
else
if(x==x->p->left)
x->p->left=y;
else
x->p->right=y;
y->left=x;
x->p=y;
}
void Right_Rotate(Tree *T,Node *x)
{
Node *y=x->left;
x->left=y->right;
if(y->right!=T->nil)
y->right->p=x;
y->p=x->p;
if(x->p==T->nil)
T->root=y;
else
if(x==x->p->right)
x->p->right=y;
else
x->p->left=y;
y->right=x;
x->p=y;
}
void Insert_Fixup(Tree *T,Node *z)
{
while(z->p->color==0)//仅仅当case 1的时候while可执行多次
{
if(z->p==z->p->p->left)
{
Node *y=z->p->p->right;
if(y->color==0)//case 1
{
z->p->color=1;
y->color=1;
z->p->p->color=0;
z=z->p->p;
}
else
{
if(z==z->p->right)
{
z=z->p;
Left_Rotate(T,z);
}
z->p->color=1;
z->p->p->color=0;
Right_Rotate(T,z->p->p);
}
}
else//下面么这段代码是跟上面的那段代码left和right交换得到的
{
Node *y=z->p->p->left;
if(y->color==0)
{
z->p->color=1;
y->color=1;
z->p->p->color=0;
z=z->p->p;
}
else
{
if(z==z->p->left)
{
z=z->p;
Right_Rotate(T,z);
}
z->p->color=1;
z->p->p->color=0;
Left_Rotate(T,z->p->p);
}
}
}
T->root->color=1;
}
void Insert(Tree *T,Node *z)
{
Node *y=T->nil;
Node *x=T->root;
while(x!=T->nil)
{
y=x;
if((z->key)<(x->key))
x=x->left;
else
x=x->right;
}
z->p=y;
if(y==T->nil)
T->root=z;
else
if((z->key)<(y->key))
y->left=z;
else
y->right=z;
z->left=T->nil;
z->right=T->nil;
z->color=0;//red
Insert_Fixup(T,z);
}
void Delete_Fixup(Tree *T,Node *x)
{
Node *w;
while(x!=T->root&&x->color==1)
{
if(x==x->p->left)
{
w=x->p->right;
if(w->color==0)
{
w->color=1;
x->p->color=0;
Left_Rotate(T,x->p);
w=x->p->right;
}
if(w->left->color==1&&w->right->color==1)
{
w->color=0;
x=x->p;
}
else
if(w->right->color==1)
{
w->left->color=1;
w->color=0;
Right_Rotate(T,w);
w=x->p->right;
}
w->color=x->p->color;
x->p->color=1;
w->right->color=1;
Left_Rotate(T,x->p);
x=T->root;
}
else
{
w=x->p->left;
if(w->color==0)
{
w->color=1;
x->p->color=0;
Right_Rotate(T,x->p);
w=x->p->left;
}
if(w->right->color==1&&w->left->color==1)
{
w->color=0;
x=x->p;
}
else
if(w->left->color==1)
{
w->right->color=1;
w->color=0;
Left_Rotate(T,w);
w=x->p->left;
}
w->color=x->p->color;
x->p->color=1;
w->left->color=1;
Right_Rotate(T,x->p);
x=T->root;
}
}
}
Node *Tree_Min(Tree *T,Node* x)
{
while(x->left!=T->nil)
x=x->left;
return x;
}
Node *Tree_Successor(Tree *T,Node* x)//后继
{
Node *y;
if(x->right!=T->nil)
return Tree_Min(T,x->right);
y=x->p;
while(y!=T->nil&&x==y->right)
{
x=y;
y=y->p;
}
return y;
}
void Delete(Tree *T,Node *z)
{
Node *y,*x;
if(z->left==T->nil||z->right==T->nil)
y=z;
else
y=Tree_Successor(T,z);//z后继
if(y->left!=T->nil)
x=y->left;
else
x=y->right;
x->p=y->p;
if(y->p==T->nil)
T->root=x;
else
if(y==y->p->left)
y->p->left=x;
else
y->p->right=x;
if(y!=z)
{
z->key=y->key;//把y中的内容复制到z中
}
if(y->color==1)
Delete_Fixup(T,x);
free(y);
}
void dfs(Tree *T,Node *x,int k)
{
if(k>=5)
return;
if(x==T->nil)
return;
cout<<"-------"<<endl;
cout<<x->key<<endl;
cout<<x->left->key<<endl;
cout<<x->right->key<<endl;
dfs(T,x->left,k+1);
dfs(T,x->right,k+1);
}
void show(Tree *T)
{
dfs(T,T->root,0);
}
Node *Search(Tree *T,Node *x,int key)
{
if(x==T->nil)
return T->nil;
if(x->key==key)
return x;
if(x->key>key)
return Search(T,x->left,key);
else
return Search(T,x->right,key);
}
int main()
{
Tree T;
Insert(&T,new Node(1));
Insert(&T,new Node(2));
Insert(&T,new Node(3));
show(&T);
Node *p=Search(&T,T.root,2);
if(p!=T.nil)
Delete(&T,p);
show(&T);
return 0;
}