C++实现的红黑树基本操作(English notes very cool!!)

作者在 2017-05-09 21:41:53 发布以下内容
#include<iostream>
#include<cstdlib>
using namespace std;

#define RED 1    
#define BLACK 0
typedef struct TreeNode
{
int Element;
int Color;
TreeNode *Parent;
TreeNode *Left;
TreeNode *Right;
TreeNode()
{
Color=BLACK;   //let initial node become black
}
}*MyRBTree;

MyRBTree NullNode=NULL;
MyRBTree Root;

void MakeEmpty(MyRBTree &T);
void InorderTraverse(const MyRBTree T);
MyRBTree Find(const MyRBTree T,int X);  
MyRBTree FindMin(const MyRBTree T);
MyRBTree FindMax(const MyRBTree T);
void LeftSingleRotate(MyRBTree X);
void RightSingleRotate(MyRBTree X);
void FixUpInsert(MyRBTree Z);  
void Insert(int Data); //insert a element by non-recursive way
void Transplant(MyRBTree U,MyRBTree V);
void FixUpDelete(MyRBTree X);
void Delete(MyRBTree &Z);
int Height(MyRBTree T);

int main()
{
NullNode=new TreeNode;
MyRBTree Temp=NULL;
int H;  //tree's height
//MakeEmpty(Root);
Root=NullNode;
int i,a[16]={1,2,3,5,6,7,9,11,12,8,15,22,17,20,21,29};
for(i=0;i<16;i++)
{
cout <<a[i] <<' ' ;
Insert(a[i]);
}
cout <<endl ; 
InorderTraverse(Root);
H=Height(Root);
cout <<endl <<"树高为 "<<H <<endl ;

Temp=FindMin(Root);
cout <<Temp->Element <<endl ;

Temp=FindMax(Root);
cout <<Temp->Element <<endl ;

Temp=Find(Root,1);      //delete 1
if(Temp)
{
   Delete(Temp);
   InorderTraverse(Root);
   cout <<endl ;
    }

Temp=Find(Root,17);  //delete 2
if(Temp)
{
Delete(Temp);
   InorderTraverse(Root);
   cout <<endl ;
    }
    
    Temp=Find(Root,22);  //delete 22
if(Temp)
{
Delete(Temp);
   InorderTraverse(Root);
   cout <<endl ;
    }
    
    Temp=Find(Root,8);  //delete 8
if(Temp)
{
Delete(Temp);
   InorderTraverse(Root);
   H=Height(Root);
   cout <<endl <<"树高为 "<<H <<endl ;
   cout <<endl ;
    }
    
MakeEmpty(Root);
return 0;
}

void MakeEmpty(MyRBTree &T)   
{
if(T!=NullNode)
{
MakeEmpty(T->Left);
MakeEmpty(T->Right);
delete T;
T=NULL;
}
}

void InorderTraverse(const MyRBTree T)
{
if(T!=NullNode)
{
InorderTraverse(T->Left);
cout <<T->Element <<' ' ;
InorderTraverse(T->Right);
}
}

MyRBTree Find(const MyRBTree T,int X)  //find a element's position
{
if(T==NULL) return NULL;
else if(X<T->Element) return Find(T->Left,X);
else if(X>T->Element) return Find(T->Right,X);
else return T;
}

MyRBTree FindMin(const MyRBTree T)  //find the min's position
{
if(T->Left!=NullNode) return FindMin(T->Left);
else return T;
}

MyRBTree FindMax(const MyRBTree T)  //find the max position
{
if(T->Right!=NullNode) return FindMax(T->Right);
else return T;
}

int Height(MyRBTree T)   //get tree's height
{
int HeightLeft;
int HeightRight;
if(T==NullNode) return 0;
HeightLeft=Height(T->Left);
HeightRight=Height(T->Right);
return HeightLeft>HeightRight?(HeightLeft+1):(HeightRight+1);
}

/*
因为RB树之间的节点连接相比AVL树多了一个Parent指针,所以比AVL的单旋转略为复杂
其增加部分主要是为了消除旧节点间的Parent和增加新节点间的Parent连接 
*/
void LeftSingleRotate(MyRBTree X)       
{
MyRBTree Y=X->Right;                                //get y
X->Right=Y->Left;                                  //1.link x and y'left by *right
if(Y->Left!=NullNode)       Y->Left->Parent=X;    //2.link y'left and x by *parent

Y->Parent=X->Parent;                              //3.link y and x'parent by *parent
if(X->Parent==NullNode)     Root=Y;               //4.root y is just have left and right
else if(X==X->Parent->Left) X->Parent->Left=Y;    //4.link x'parent and y by *left
else                        X->Parent->Right=Y;   //4.link x'parent and y by *right

Y->Left=X;                                        //5.link y and x by *left
X->Parent=Y;                                      //6.link x and y by *parent //6 steps:because 3 nodes and every nodes include 2 linking ways
}

void RightSingleRotate(MyRBTree X) //a same theory
{
MyRBTree Y=X->Left;
X->Left=Y->Right;
if(Y->Right!=NullNode)       Y->Right->Parent=X; 

Y->Parent=X->Parent;
if(X->Parent==NullNode)      Root=Y;
else if(X==X->Parent->Left)  X->Parent->Left=Y;
else                         X->Parent->Right=Y;

Y->Right=X;
X->Parent=Y;


/*
建议参考《算法导论》中的红黑树,里面考虑的比较全面
这里基本是按照书上的图编程上去的
还有就是自己也要画图 
*/
void FixUpInsert(MyRBTree Z)
{
while(Z->Parent->Color==RED)
{
if(Z->Parent==Z->Parent->Parent->Left)  //case 1.a  just re-color
{
MyRBTree Y=Z->Parent->Parent->Right;    //if Z'parent is at left
if(Z->Color==RED)
{
Z->Parent->Color=BLACK;
Y->Color=BLACK;
Z->Parent->Parent->Color=RED;
Z=Z->Parent->Parent;
}
else 
   {
       if(Z==Z->Parent->Right)     //case 2.a  need rotate and re-color 
       {
       Z=Z->Parent;
       LeftSingleRotate(Z);
   }
   Z->Parent->Color=BLACK;  //case 3.a
   Z->Parent->Parent->Color=RED;
   RightSingleRotate(Z->Parent->Parent);
   }
}
else              
{
MyRBTree Y=Z->Parent->Parent->Left;  //if Z'parent is at right,a same theory such as Z'parent is at left
if(Y->Color==RED)    //case 1.b
{
Z->Parent->Color=BLACK;
Y->Color=BLACK;
Z->Parent->Parent->Color=RED;
Z=Z->Parent->Parent;
}
else
{
if(Z==Z->Parent->Left)  //case 2.b
{
Z=Z->Parent;
RightSingleRotate(Z);
}
Z->Parent->Color=BLACK;  //case 3.b
Z->Parent->Parent->Color=RED;
LeftSingleRotate(Z->Parent->Parent);
}
}
}
Root->Color=BLACK;
}


void Insert(int Data) //insert a element by non-recursive way
{
MyRBTree Z=new TreeNode;
Z->Element=Data;
Z->Color=RED;
Z->Parent=Z->Left=Z->Right=NullNode;
MyRBTree Y=NullNode;
MyRBTree X=Root;
while(X!=NullNode)   //find the position Z should insert
{
Y=X;
if(Z->Element<X->Element)
   X=X->Left;
else 
   X=X->Right;
}
Z->Parent=Y;    
if(Y==NullNode)
   Root=Z;
else if(Z->Element<Y->Element)
       Y->Left=Z;
    else 
       Y->Right=Z;
FixUpInsert(Z);
}


void Transplant(MyRBTree U,MyRBTree V)  //
{
if(U->Parent==NullNode)
   Root=V;
else if(U==U->Parent->Left)
       U->Parent->Left=V;
else if(U==U->Parent->Right)
       U->Parent->Right=V;
V->Parent=U->Parent;
}

void FixUpDelete(MyRBTree X)  
{
while(X!=Root&&X->Color==BLACK)
{
if(X==X->Parent->Left)
{
MyRBTree W=X->Parent->Right;     //x's brother

if(W->Color==RED)   //case 1.a
{
W->Color=BLACK;
X->Parent->Color=RED;
LeftSingleRotate(X->Parent);   //generally use X'p ,not W'p
W=X->Parent->Right;
}
if(W->Left->Color==BLACK&&W->Right->Color==BLACK) //case 2.a
{
W->Color=RED;
X=X->Parent;
}
else     
{
if(W->Left->Color==RED)  //case 3.a
{
W->Color=RED;
W->Left->Color=BLACK;
RightSingleRotate(W);
W=X->Parent->Right;
   }
W->Color=W->Parent->Color;  //case 3.a >> case 4.a
W->Parent->Color=BLACK;
W->Right->Color=BLACK;
LeftSingleRotate(X->Parent);
X=Root;  //case 4.a >>loop end 
}
}
else
{
MyRBTree W=X->Parent->Left;

if(W->Color==RED)  //case 1.b
{
W->Color=BLACK;
X->Parent->Color=RED;
RightSingleRotate(X->Parent);
W=X->Parent->Left;
}
if(W->Left->Color==BLACK&&W->Right->Color==BLACK) //case 2.b
{
W->Color=RED;
X=X->Parent;
}
else
{
if(W->Right->Color==RED)      
{
W->Color=BLACK;        //case 3.b
W->Right->Color=BLACK;
LeftSingleRotate(W);
W=X->Parent->Left;
}
W->Color=W->Parent->Color;  //case 3.b >> case 4.b
W->Parent->Color=BLACK;
W->Left->Color=BLACK;
RightSingleRotate(X->Parent);  //case 4.b >> loop end
X=Root; 
}
}
}
X->Color=BLACK;
}

void Delete(MyRBTree &Z)
{
MyRBTree X=NULL;
MyRBTree Y=Z;
int YColor=Y->Color; //record y original color

if(Z->Left==NullNode)  //if Z just have right
{
X=Z->Right;
Transplant(Z,Z->Right);
}
else if(Z->Right==NullNode) //if Z just have left
{
X=Z->Left;
Transplant(Z,Z->Left);
}
else    //Z have two childnode
{
Y=FindMin(Z->Right);
YColor=Y->Color;
X=Y->Right;
if(Y->Parent==Z)  
   X->Parent=Y;
else    //if y isn't z'childnode
{
Transplant(Y,Y->Right);   //let y's rightnode become y ,and then change z' pointer
Y->Right=Z->Right;
Y->Right->Parent=Y;  //let Y'before is a RBT
}
Transplant(Z,Y);        //let y become z
Y->Left=Z->Left;
Y->Left->Parent=Y;
Y->Color=Z->Color;
}
if(YColor==BLACK)   //not balanced because there is a black node become red
   FixUpDelete(X);
}
c++基础 | 阅读 1727 次
文章评论,共1条
飞机火车(作者)
2017-05-09 21:43
1
经过8天的学习终于弄出来了
哈哈,承认自己是笨鸟
游客请输入验证码