// RBTree.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <iostream> using namespace std; template<typename T> 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(data<p->data) 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<T>::*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<typename T> RB_Tree<T>::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<typename T> void RB_Tree<T>::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<typename T> void RB_Tree<T>::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<typename T> bool RB_Tree<T>::Insert(T data) { bool bRet; RB_Node *pNode; pNode=new RB_Node; pNode->data=data; bRet=Insert(*pNode); return bRet; } template<typename T> bool RB_Tree<T>::Insert(RB_Node &node) { RB_Node *p,*pre; pre=pNil; p=pRoot; while(p!=pNil){ pre=p; if(node.data<p->data) 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.data<pre->data) pre->lChild=&node; else pre->rChild=&node; //test printf("data %2d has been added in case ",node.data); InsertFixup(&node); return true; } template<typename T> void RB_Tree<T>::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<typename T> bool RB_Tree<T>::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<typename T> bool RB_Tree<T>::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<<endl; return bRet; } template<typename T> void RB_Tree<T>::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<typename T> void RB_Tree<T>::Free(RB_Node *x) { delete x; } int _tmain(int argc, _TCHAR* argv[]) { RB_Tree<int> rb_tree; int times=100; for(int i=0;i<times;++i){ rb_tree.Insert(-i); rb_tree.Insert(i); } 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
本代码与其他的红黑树代码最大的不同就是,用到了类的成员函数指针来减少代码冗余:在插入和删除节点后,都要对红黑树进行调节。而根据被插入或删除点时左子节点还是右子节点要进行分情况编写代码,而这两部分的代码是十分雷同的。所以我在源码中用到成员函数指针等技术来消除这种冗余。