您的位置:首页 > 其它

红黑树(RED-BLACK TREE)的插入和删除

2014-07-12 16:06 507 查看
红黑树的插入和删除会需要用到旋转和颜色翻转。颜色翻转和旋转的主要目的是为了保证红黑树的5个性质,插入最直接来讲可能会导致根结点是红色(树为空),红色结点的子结点为红色,这是需要进行红黑调整以及子树翻转。删除最直接的结果就是删除了黑色结点,那么导致沿着该结点的路径上的黑色结点数目发生变化,此时需要翻转颜色和旋转子树来平衡。

红黑树的左旋和右旋



图1 左旋和右旋示意图

左旋的伪代码:

LEFT-ROTATE(T,x)
y = x.right
x.right = y.left
if y.left != nil(T)
y.left.p = x
y.p = x.p
if x.p == nil(T)
T.root = y
elseif x == x.p.left
x.p.left = y
else x.p.right = y
y.left = x
x.p = y


代码很好理解,不用赘述,右旋可以参照给出,很简单。
红黑树的插入情况可以修改二叉查找树的插入函数完成插入,同理删除情况也是如此。

插入可能导致的情形及应对的策略有下面几种:



图2 插入的情形(一侧)
上述3种情形还有三种对称的情形。

删除的情形以及其应对的策略如下:



图3 删除的情形(一侧)
代码:
#include <iostream>
#include <assert.h>
#include <stack>
#include <queue>
#include <iomanip>
using namespace std;

#define BLACK 0
#define RED 1
typedef struct RBTreeNode* RBTree;
typedef struct RBTreeNode{
int data;
int color;
RBTree lchild,rchild,parent;
} RBTreeNode ;

RBTree createNode(int key)
{
RBTree ptr = new RBTreeNode;
ptr->data = key;
ptr->parent = NULL;
ptr->color = RED;
ptr->lchild = NULL;
ptr->rchild = NULL;
return ptr;
}

RBTree& grandparent(RBTree ptr)
{
/* parameter n is short for node */
return ptr->parent->parent;
}

RBTree uncle(RBTree n)
{
/* parameter n is short for node */
if ( n->parent == grandparent(n)->lchild)
return grandparent(n)->rchild;
else
return grandparent(n)->lchild;
}
RBTree minimum(RBTree ptr)
{
while (ptr->lchild != NULL) {
ptr = ptr->lchild;
}
return ptr;
}
RBTree succ(RBTree ptr)
{
if (ptr->rchild != NULL)
return minimum(ptr->rchild);
/*RBTree y = n->parent;
while (y != NULL && n == y->rchild){
n = y;
y = y->parent;
}
return y;*/
}

RBTree leftRotate(RBTree *T,RBTree x)
{
/*
|
x
/ \
#   y
/ \
# #
*/
RBTree y = NULL;
RBTree root =NULL;
y = x->rchild;

x->rchild  = y->lchild;
if (y->lchild != NULL) {
y->lchild->parent = x;
}

y->parent = x->parent;
if (x->parent == NULL)
{
root = y;// x = y?
}
else if (x->parent->lchild == x)
x->parent->lchild = y;
else
x->parent->rchild = y;
y->lchild = x;
x->parent = y;
if (root)
*T = root;
return y;
}

RBTree rightRotate(RBTree *T,RBTree y)
{

/*
|
y
/ \
x   #
/ \
# #
*/

RBTree x =NULL;
x = y->lchild;
RBTree root = NULL;

y->lchild = x->rchild;

if (NULL != x->rchild) {
x->rchild->parent = y;
cout<<"Runned?"<<endl;
}

if (y->parent != NULL)
x->parent = y->parent;
else
x->parent = NULL;

if ((y)->parent == NULL)
root = x;
else {
if (y->parent->rchild = y)
y->parent->rchild = x;
else
y->parent->lchild = x;
}

x->rchild = y;
y->parent = x;
if (root)
*T = root;
return  x;
}

void RBInsertFixup(RBTree *T,RBTree z)
{
RBTree y;
RBTree p;
while ((p = z->parent) != NULL && p->color == RED)
{
if (p == grandparent(z)->lchild){
/*  parent of z is the lef child of grand parent of z */
y = uncle(z);
if (y != NULL && y->color == RED){
/* case 1 : color flip*/
z->parent->color = BLACK;
grandparent(z)->color = RED;
y->color = BLACK;
z = grandparent(z);
}
else {
if (z == z->parent->rchild) {
/* case 2 */
z = z->parent;
leftRotate(T,z);
}
//* case 3*/ /
z->parent->color = BLACK;
grandparent(z)->color = RED;
rightRotate(T,z->parent->parent);
}
}
else {
/* z->p = z->p->p->rchild */
y = uncle(z);
if (y != NULL && y->color == RED){
/*case 4 */
z->parent->color = BLACK;
grandparent(z)->color = RED;
y->color = BLACK;
z = grandparent(z);
}
else {
if (z == z->parent->lchild) {
/*case 5*/
z = z->parent;
rightRotate(T,z);
}
/*case 6*/
z->parent->color = BLACK;
grandparent(z)->color = RED;
leftRotate(T,z->parent->parent);
}
}
}
(*T)->color = BLACK;
}

void RBDeleteFixup(RBTree *T,RBTree xp,RBTree x)
{
/* xp is parent of x */
RBTree w;
while( x != *T && (x == NULL || x->color == BLACK))
{
if (x == xp->lchild){
/* w is sibling of x */
w = xp->rchild;
if (w->color == RED){
//case 1
w->color = BLACK;
x->parent->color = RED;
leftRotate(T,x->parent);
w = xp->rchild;
}
if ((w->lchild == NULL || w->lchild->color == BLACK) &&
(w->rchild == NULL || w->rchild->color == BLACK)){
//case 2
w->color = RED;
x = xp;
xp = xp->parent;
}
else {
if (w->rchild == NULL || w->rchild->color == BLACK){
// case 3
w->lchild->color = BLACK;
w->color = RED;
rightRotate(T,w);
w = xp->rchild;
}
// case 4
w->color = xp->color;
xp->color = BLACK;
w->rchild->color = BLACK;
leftRotate(T,xp);
x = *T;
}
}
else {
/* x == xp->rchild and  w is sibling of x*/
w = xp->lchild;
if (w->color == RED){
//case 1
w->color = BLACK;
xp->color = RED;
rightRotate(T,xp);
w = xp->lchild;
}
if ((w->lchild == NULL || w->lchild->color == BLACK) &&
(w->rchild == NULL || w->rchild->color == BLACK)){
//case 2
w->color = RED;
x = xp;
xp = xp->parent;
}
else {
if (w->lchild == NULL || w->lchild->color == BLACK){
// case 3
w->rchild->color = BLACK;
w->color = RED;
leftRotate(T,w);
w = xp->lchild;
}
// case 4
w->color = xp->color;
xp->color = BLACK;
w->lchild->color = BLACK;
rightRotate(T,xp);
x = *T;
}
}
}
if (x != NULL)
x->color = BLACK;
}

void RBInsert(RBTree *T,int key)
{
RBTree z = createNode(key);
assert(z != NULL);

RBTree y = NULL;
RBTree x = *T;

while (x != NULL) {
y = x;
if ( z->data < x->data)
x = x->lchild;
else if (z->data == x->data) {
cout<<"Key = "<<z->data<<" is already in the RB-Tree."<<endl;
delete z;
return;
}
else {
x = x->rchild;
}
}

z->parent = y;

if (y == NULL) {
*T = z;
}
else if (z->data < y->data) {
y->lchild = z;
}
else {
y->rchild = z;
}
z->lchild = NULL;
z->rchild = NULL;
z->color = RED;
RBInsertFixup(T,z);
}

void RBDelete(RBTree *T,int key)
{
RBTree z = *T;
RBTree x,y;
x = y = NULL;
bool found = false;
while ( z != NULL) {
if (key < z->data)
z = z->lchild;
else if (key > z->data)
z = z->rchild;
else {
found = true;
break;
}
}

if (!found) {
cout<<"Key = "<<key<<" is not in the tree."<<endl;
return;
}
/* copy data of y into z and delete y*/
if (z->lchild == NULL || z->rchild == NULL)
y = z;
else
y = succ(z);
/* x will be subtree of y */
if (y->lchild != NULL) {
x = y->lchild;
}
else
/* is it ok? */
x = y->rchild;

/* x link to parent of y */
if (x != NULL)
x->parent = y->parent;

if(y->parent == NULL) {
/* if y is the root of Tree */
*T = x;
}
else if (y == y->parent->lchild)
y->parent->lchild = x;
else
y->parent->rchild = x;
if (y != z) {
/* copy data of y into z */
z->data = y->data;
}
if (y->color == BLACK)
RBDeleteFixup(T,y->parent,x);
delete y;
}

inline int max(int a,int b)
{
return a>b?a:b;
}
int Height(RBTree T)
{
if (T == NULL)
return 0;
else
return 1 + max(Height(T->lchild), Height(T->rchild));
}
void MakeMat(RBTree T,int root_x,int root_y,int step,int **m)
{
int lChildPos,rChildPos;
lChildPos = root_x - step;
rChildPos = root_x + step;
if (T == NULL)
return;
else
{
m[root_y][root_x] = 1;
MakeMat(T->lchild,lChildPos,root_y+1,step>>1,m);
MakeMat(T->rchild,rChildPos,root_y+1,step>>1,m);
}
}

void RBTreeDisplay(RBTree T)
{
if(T == NULL)
return;
/* init placehold flags m[h][len] */
int h = Height(T);
int len = (1<<h) - 1;
int row = h;
int **m = new int*[row];
for(int i= 0;i<row;i++){
m[i] = new int[len];
memset(m[i],0,len*sizeof(int));
}
/* get level order traversal sequence */
vector<RBTree> v;
queue<RBTree> q;
queue<RBTree> qt;
q.push(T);
RBTree pt;
while(!q.empty())
{
pt = q.front();
if (pt->lchild != NULL)
q.push(pt->lchild);
if(pt->rchild != NULL)
q.push(pt->rchild);
v.push_back(pt);
q.pop();
}
/* generate output matrix  plus '/' and '\\' m[2*h-1][len] */
MakeMat(T,len>>1,0,len+1>>2,m);
/* generate output */
int cnt = 0;
int width = 2;
for(int i = 0; i < row; i++)
{
for(int j = 0; j < len; j++)
{
if(m[i][j])
{
cout<<((v[cnt])->color?'R':'B')<<":"<<(v[cnt])->data;
cnt++;
}
else
cout<<setw(width)<<' ';
}
cout<<endl;
}

}
int main()
{
RBTree T = NULL;
int i;
int a[] = {12,1,9,0,2,11,7};
for (i = 0; i < 7; i++) {
cout<<"Inserting key = "<<a[i]<<endl;
RBInsert(&T,a[i]);
RBTreeDisplay(T);
cout<<endl;
cout<<"----------------------------------------------------------"<<endl;;
}
cout<<"Inserting key = "<<2<<endl;
RBInsert(&T,2);
RBTreeDisplay(T);
cout<<endl;
cout<<"----------------------------------------------------------"<<endl;

cout<<"Deleting key = "<<2<<endl;
RBDelete(&T,2);
RBTreeDisplay(T);
cout<<endl;
cout<<"----------------------------------------------------------"<<endl;

cout<<"Deleting key = "<<7<<endl;
RBDelete(&T,7);
RBTreeDisplay(T);
cout<<endl;
cout<<"----------------------------------------------------------"<<endl;
for (i = 0;i < 7;i++)
{
cout<<"Deleting key = "<<a[i]<<endl;
RBDelete(&T,a[i]);
RBTreeDisplay(T);
cout<<endl;
cout<<"----------------------------------------------------------"<<endl;
}
}


测试结果:

Inserting key = 12
B:12

----------------------------------------------------------
Inserting key = 1
B:12
R:1

----------------------------------------------------------
Inserting key = 9
B:9
R:1  R:12

----------------------------------------------------------
Inserting key = 0
B:9
B:1      B:12
R:0

----------------------------------------------------------
Inserting key = 2
B:9
B:1      B:12
R:0  R:2

----------------------------------------------------------
Inserting key = 11
B:9
B:1      B:12
R:0  R:2  R:11

----------------------------------------------------------
Inserting key = 7
B:9
R:1              B:12
B:0      B:2      R:11
R:7

----------------------------------------------------------
Inserting key = 2
Key = 2 is already in the RB-Tree.
B:9
R:1              B:12
B:0      B:2      R:11
R:7

----------------------------------------------------------
Deleting key = 2
B:9
R:1      B:12
B:0  B:7  R:11

----------------------------------------------------------
Deleting key = 7
B:9
B:1      B:12
R:0      R:11

----------------------------------------------------------
Deleting key = 12
B:9
B:1      B:11
R:0

----------------------------------------------------------
Deleting key = 1
B:9
B:0  B:11

----------------------------------------------------------
Deleting key = 9
B:11
R:0

----------------------------------------------------------
Deleting key = 0
B:11

----------------------------------------------------------
Deleting key = 2
Key = 2 is not in the tree.
B:11

----------------------------------------------------------
Deleting key = 11

----------------------------------------------------------
Deleting key = 7
Key = 7 is not in the tree.

----------------------------------------------------------
REF:

1,算法导论 红黑树章节
2,http://chiyx.iteye.com/blog/1663013
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: