// RBTree.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include
using namespace std;
template
class RB_Tree
{
class RB_Node;
enum Color {BLACK,RED};
public:
RB_Tree();
bool Insert(T data);
bool Insert(RB_Node &node);
bool Delete(T data);
bool Delete(RB_Node *node);
RB_Node* FindData(T data)
{
RB_Node *p=pRoot;
RB_Node *pFound=NULL;
while(p!=pNil)
if(datadata)
p=p->lChild;
else if(data>p->data)
p=p->rChild;
else{
pFound=p;
break;
}
return pFound;
}
class RB_Node{
public:
RB_Node():lChild(Children[0]),rChild(Children[1])
{
parent=NULL;
Children[0]=Children[1]=NULL;
}
// To force two pointers to be together.
// For later use of "lChild+1" in delete operation
RB_Node *Children[2];
(RB_Node *)& lChild;
(RB_Node *)& rChild;
RB_Node *parent;
T data;
Color color;
};
private:
void leftRotate(RB_Node *const x);
void rightRotate(RB_Node *const x);
void InsertFixup(RB_Node *x);
void DeleteFixup(RB_Node *x);
void Free(RB_Node *x);
typedef void (RB_Tree::*RotateFunc)(RB_Node *const );
RotateFunc pRotates[2];
RB_Node nil;
RB_Node *pRoot,*pNil;
};
enum Twist {LR=0,RL=1,LL=2,RR=3};
template
RB_Tree::RB_Tree()
{
pRotates[0]=&RB_Tree::leftRotate;
pRotates[1]=&RB_Tree::rightRotate;
//nil initialization
pNil=new RB_Node;
pNil->color=BLACK;
pRoot=pNil;
//pNil's children and points are useless
//pNil's parent is useful in deleting fixup.
pNil->lChild=pNil->rChild=pNil->parent=NULL;
}
template
void RB_Tree::leftRotate(RB_Node *const x)
{
RB_Node *y=x->rChild;
//This case won't be happened when the function used inside the class
if(pNil==y)
return;
x->rChild=y->lChild;
if(pNil!=y->lChild)
y->lChild->parent=x;
y->parent=x->parent;
if(pNil==x->parent)
pRoot=y;
else if(x->parent->lChild==x)
x->parent->lChild=y;
else
x->parent->rChild=y;
y->lChild=x;
x->parent=y;
}
template
void RB_Tree::rightRotate(RB_Node *const y)
{
RB_Node *x=y->lChild;
//This case won't be happened when the function used inside the class
if(pNil==x)
return;
y->lChild=x->rChild;
if(pNil!=x->rChild)
x->rChild->parent=y;
x->parent=y->parent;
if(pNil==y->parent)
pRoot=x;
else if(y->parent->lChild==y)
y->parent->lChild=x;
else
y->parent->rChild=x;
x->rChild=y;
y->parent=x;
}
template
bool RB_Tree::Insert(T data)
{
bool bRet;
RB_Node *pNode;
pNode=new RB_Node;
pNode->data=data;
bRet=Insert(*pNode);
return bRet;
}
template
bool RB_Tree::Insert(RB_Node &node)
{
RB_Node *p,*pre;
pre=pNil;
p=pRoot;
while(p!=pNil){
pre=p;
if(node.datadata)
p=p->lChild;
else if(node.data==p->data){
printf("Data already exited.\n");
return false;
}
else
p=p->rChild;
}
node.parent=pre;
node.lChild=node.rChild=pNil;
node.color=RED;
if(pre==pNil)
pRoot=&node;
else if(node.datadata)
pre->lChild=&node;
else
pre->rChild=&node;
//test
printf("data %2d has been added in case ",node.data);
InsertFixup(&node);
return true;
}
template
void RB_Tree::InsertFixup(RB_Node *x)
{
while(1){
//case 1
if(x==pRoot){
x->color=BLACK;
printf("1\n");
return;
}
//case 2
else if(x->parent->color==BLACK){
printf("2\n");
return;
}
//case 3 : parent and uncle both are red
if(x->parent->parent->lChild->color==x->parent->parent->rChild->color){
x->parent->parent->lChild->color=BLACK;
x->parent->parent->rChild->color=BLACK;
x->parent->parent->color=RED;
x=x->parent->parent;
printf("3");
}
//case 4:uncle node is black
else{
Twist twist;
//case 4.1: uncle node is grandparent node's right node
if(x->parent->parent->lChild->color==RED){
if(x->parent->lChild->color==RED)
twist=LL;
else
twist=LR;
}
else if(x->parent->lChild->color==RED)
twist=RL;
else
twist=RR;
/* enum value
LR : 0 RL : 1 LL : 2 RR : 3
*/
if(twist==LR||twist==RL){
x=x->parent;
(this->*pRotates[twist])(x);
}
printf("4(%d)\n",twist);
x=x->parent->parent;
int opTwist=1-twist%2;
(this->*pRotates[opTwist])(x);
x->color=RED;
x->parent->color=BLACK;
return;
}
}
}
template
bool RB_Tree::Delete(RB_Node *p)
{
RB_Node *del,*pre,**pParentToDel,*successor;
if(pNil==p){
printf("Nil can't be deleted \n");
return false;
}
if(pNil==p->parent)
pParentToDel=&pRoot;
else if(p->parent->lChild==p)
pParentToDel=&(p->parent->lChild);
else
pParentToDel=&(p->parent->rChild);
if(pNil==p->lChild){
del=p;
p=p->rChild;
p->parent=del->parent;
*pParentToDel=p;
}
else if(pNil==p->rChild){
del=p;
p=p->lChild;
p->parent=del->parent;
*pParentToDel=p;
}
else{
pre=p;
del=p->lChild;
while(del->rChild!=pNil){
pre=del;
del=del->rChild;
}
p->data=del->data;
successor=del->lChild;
if(del==pre->lChild)
pre->lChild=successor;
else
pre->rChild=successor;
successor->parent=pre;
p=successor;
}
if(del->color==BLACK)
DeleteFixup(p);
Free(del);
return true;
}
template
bool RB_Tree::Delete(T data)
{
RB_Node *pFound=NULL;
bool bRet;
pFound=FindData(data);
if(NULL==pFound)
return false;
printf("%d has been deleted by ",data);
bRet=Delete(pFound);
cout<
void RB_Tree::DeleteFixup(RB_Node *x)
{
RB_Node *brother;
while(x!=pRoot&&x->color==BLACK)
{
int direction,opDirection;
if(x==x->parent->lChild)
direction=0;
else
direction=1;
opDirection=1-direction;
brother=x->parent->Children[opDirection]; // <==> brother=*(&(x->parent->lChild)+opDirection);
//case 1:Parent's black and brother's red.
//Rotate brother up to make parent red to enter case 2, 3, 4.
if(brother->color==RED){
brother->color=BLACK;
brother->parent->color=RED;
(this->*pRotates[direction])(x->parent);
brother=x->parent->Children[opDirection];
printf("1");
}
//case 2;brother's black and brother's children are both Black
//mark brother to red. Then the problem of balance is lifted up to parent
if(brother->lChild->color==BLACK&&brother->rChild->color==BLACK){
brother->color=RED;
x=x->parent;
printf("2");
}
else{
//case 3: Brother's son closer to me is red,the one distanter to me is black
//Rotate to enter case 4
if(brother->Children[opDirection]->color==BLACK){
(this->*pRotates[opDirection])(brother);
brother->color=RED;
brother=brother->parent;
brother->color=BLACK;
cout<<3;
}
//case 4:brother's son distanter to me is red:we can rotate
//brother and this son up and make the son black to balance the whole tree.
brother->color=x->parent->color;
x->parent->color=BLACK;
(this->*pRotates[direction])(x->parent);
brother->Children[opDirection]->color=BLACK;
//to quite
x=pRoot;
cout<<4;
}
}
x->color=BLACK;
}
template
void RB_Tree::Free(RB_Node *x)
{
delete x;
}
int _tmain(int argc, _TCHAR* argv[])
{
RB_Tree rb_tree;
int times=100;
for(int i=0;i-times;--i)
rb_tree.Delete(i);
return 0;
}
这是本人写的实现红黑树的源码。
红黑树的实现原理具体请参见《算法导论》和v_JULY_v大神写的关于红黑树的专题:http://blog.csdn.net/v_july_v/article/category/774945
本代码与其他的红黑树代码最大的不同就是,用到了类的成员函数指针来减少代码冗余:在插入和删除节点后,都要对红黑树进行调节。而根据被插入或删除点时左子节点还是右子节点要进行分情况编写代码,而这两部分的代码是十分雷同的。所以我在源码中用到成员函数指针等技术来消除这种冗余。