红黑树C++完整源码

来源:互联网 发布:ajax提交json form 编辑:程序博客网 时间:2024/05/16 01:02
// 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 operationRB_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 classif(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;elsex->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 classif(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;}elsep=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;elsepre->rChild=&node;//testprintf("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 1if(x==pRoot){x->color=BLACK;printf("1\n");return;}//case 2else if(x->parent->color==BLACK){printf("2\n");return;}//case 3 : parent and uncle both are redif(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 blackelse{Twist twist;//case 4.1: uncle node is grandparent node's right nodeif(x->parent->parent->lChild->color==RED){if(x->parent->lChild->color==RED)twist=LL;elsetwist=LR;}else if(x->parent->lChild->color==RED)twist=RL;elsetwist=RR;/* enum valueLR : 0RL : 1LL : 2RR : 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);elsepParentToDel=&(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;elsepre->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;elsedirection=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 parentif(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 4if(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 quitex=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

本代码与其他的红黑树代码最大的不同就是,用到了类的成员函数指针来减少代码冗余:在插入和删除节点后,都要对红黑树进行调节。而根据被插入或删除点时左子节点还是右子节点要进行分情况编写代码,而这两部分的代码是十分雷同的。所以我在源码中用到成员函数指针等技术来消除这种冗余。

原创粉丝点击