//
// main.cpp
// Data Structure TRY1
//
// Created by zr9558 on 6/7/13.
// Copyright (c) 2013 zr9558. All rights reserved.
//
// Introduction to Algorithms: Chapter 13 Red Black Tree
#include<iostream>
using namespace std;
#include<math.h>
template<typename Comparable>
class RedBlackTree
{
public:
RedBlackTree()
{
NIL=new RBNode();
NIL->parent=NIL->left=NIL->right=NIL;
root=NIL;
}
RedBlackTree( const RedBlackTree &rhs)
{
NIL=new RBNode();
NIL->parent=NIL->left=NIL->right=NIL;
root=clone(rhs.root);
}
const RedBlackTree & operator= ( const RedBlackTree &rhs)
{
if( this!=&rhs)
{
makeEmpty(root);
delete NIL;
NIL=new RBNode();
NIL->parent=NIL->left=NIL->right=NIL;
root=clone(rhs.root);
}
return *this;
}
~ RedBlackTree()
{
makeEmpty(root);
delete NIL;
}
bool contain( const Comparable &x) const
{
RBNode *temp=Tree_Search(root, x);
if( temp==NIL) return false;
else return true;
}
const Comparable & findMin() const
{
return Tree_Minimum(root)->key;
}
const Comparable & findMax() const
{
return Tree_Maximum(root)->key;
}
bool isEmpty() const
{
return root==NIL;
}
void insert( const Comparable &k)
{
RBNode *t=new RBNode(k);
RB_Insert(t);
}
void remove( const Comparable &k)
{
RBNode * t=Tree_Search(root, k);
if( t!=NIL)
{
RBNode * y=RB_Delete(t);
delete y;
}
}
void print()
{
Print(root,0);
}
void printInOrder()
{
PrintInOrder(root);
cout<<endl;
}
enum {RED, BLACK};
private:
struct RBNode
{
Comparable key;
RBNode *left, *right, *parent;
int color;
RBNode( const Comparable &theElement=Comparable(), RBNode *lt=NULL, RBNode *rt=NULL,
RBNode *pt=NULL, int c=BLACK): key(theElement), left(lt), right(rt), parent(pt), color(c){}
};
RBNode *root;
RBNode *NIL;
//assume x->right!=NIL and root->parent==NIL;
void Left_Rotate( RBNode *x)
{
RBNode *y=x->right; // set y
x->right=y->left; // Turn y's left subtree into x's right subtree
if( y->left!=NIL) y->left->parent=x;
y->parent=x->parent; // Link x's parent to y
if( x->parent==NIL)
root=y;
else if( x==x->parent->left)
x->parent->left=y;
else x->parent->right=y;
y->left=x;
x->parent=y;
}
//assume x->left!=NIL and root->parent==NIL
void Right_Rotate( RBNode *x)
{
RBNode *y=x->left;
x->left=y->right;
if( y->right!=NIL)
y->right->parent=x;
y->parent=x->parent;
if( x->parent==NIL)
root=y;
else if( x==x->parent->left)
x->parent->left=y;
else x->parent->right=y;
y->right=x;
x->parent=y;
}
void RB_Insert_Fixup( RBNode *z)
{
while( z->parent->color==RED)
{
if( z->parent==z->parent->parent->left)
{
RBNode *y=z->parent->parent->right;
if( y->color==RED) // case 1
{
z->parent->color=BLACK;
y->color=BLACK;
z->parent->parent->color=RED;
z=z->parent->parent;
}
else
{
if( z==z->parent->right) // case 2
{
z=z->parent;
Left_Rotate(z);
}
// case 3; case 2 will change to case 3
z->parent->color=BLACK;
z->parent->parent->color=RED;
Right_Rotate(z->parent->parent);
}
}
else
{
RBNode *y=z->parent->parent->left;
if( y->color==RED) // case 1
{
z->parent->color=BLACK;
y->color=BLACK;
z->parent->parent->color=RED;
z=z->parent->parent;
}
else
{
if( z==z->parent->left) // case 2
{
z=z->parent;
Right_Rotate(z);
}
// case 3; case 2 will change to case 3
z->parent->color=BLACK;
z->parent->parent->color=RED;
Left_Rotate(z->parent->parent);
}
}
}
root->color=BLACK;
}
void RB_Insert( RBNode *z)
{
RBNode *y=NIL;
RBNode *x=root;
while( x!=NIL)
{
y=x;
if( z->key<x->key)
x=x->left;
else x=x->right;
}
z->parent=y;
if( y==NIL)
root=z;
else if( z->key < y->key)
y->left=z;
else y->right=z;
z->left=NIL;
z->right=NIL;
z->color=RED;
RB_Insert_Fixup(z);
}
RBNode *Tree_Minimum( RBNode *x) const
{
while( x->left!=NIL)
x=x->left;
return x;
}
RBNode *Tree_Maximum( RBNode *x) const
{
while( x->right!=NIL)
x=x->right;
return x;
}
RBNode *Tree_Successor( RBNode *x)
{
if( x->right!=NIL)
return Tree_Minimum(x->right);
RBNode *y=x->parent;
while( y!=NIL && x==y->right)
{
x=y;
y=y->parent;
}
return y;
}
RBNode *Tree_Search( RBNode *x, const Comparable &k) const
{
if( x==NIL || k==x->key)
return x;
if( k<x->key)
return Tree_Search(x->left, k);
else return Tree_Search(x->right, k);
}
void RB_Delete_Fixup( RBNode *x)
{
while( x!=root && x->color==BLACK)
{
if( x==x->parent->left)
{
RBNode *w=x->parent->right;
if( w->color==RED) // case 1
{
w->color=BLACK;
x->parent->color=RED;
Left_Rotate(x->parent);
w=x->parent->right;
}
if( w->left->color==BLACK && w->right->color==BLACK) // case 2
{
w->color=RED;
x=x->parent;
}
else
{
if( w->right->color==BLACK) // case 3
{
w->left->color=BLACK;
w->color=RED;
Right_Rotate(w);
w=x->parent->right;
}
w->color=x->parent->color;
x->parent->color=BLACK;
w->right->color=BLACK;
Left_Rotate(x->parent);
x=root;
}
}
else
{
RBNode *w=x->parent->left;
if( w->color==RED) // case 1
{
w->color=BLACK;
x->parent->color=RED;
Right_Rotate(x->parent);
w=x->parent->left;
}
if( w->right->color==BLACK && w->left->color==BLACK) // case 2
{
w->color=RED;
x=x->parent;
}
else
{
if( w->left->color==BLACK) // case 3
{
w->right->color=BLACK;
w->color=RED;
Left_Rotate(w);
w=x->parent->left;
}
w->color=x->parent->color;
x->parent->color=BLACK;
w->left->color=BLACK;
Right_Rotate(x->parent);
x=root;
}
}
}
x->color=BLACK;
}
RBNode * RB_Delete( RBNode *z)
{
RBNode *y=NULL;
if( z->left==NIL || z->right==NIL)
y=z;
else y=Tree_Successor(z);
RBNode *x=NULL;
if( y->left!=NIL)
x=y->left;
else x=y->right;
x->parent=y->parent;
if( y->parent==NIL)
root=x;
else if( y==y->parent->left)
y->parent->left=x;
else y->parent->right=x;
if(y!=z)
z->key=y->key;
if( y->color==BLACK)
RB_Delete_Fixup(x);
return y;
}
RBNode *clone( RBNode *t) const
{
if( t->left==t || t->right==t) // t==NIL
return NIL;
else return new RBNode(t->key, clone(t->left), clone(t->right), t->parent, t->color);
}
void Print( RBNode *t, int level)
{
if( t!=t->left) // t!=NIL
{
Print(t->right,level+1);
for( int i=0; i<4*level; ++i)
cout<<" ";
cout<<t->key<<" "<<t->color<<endl;
Print(t->left, level+1);
}
}
void PrintInOrder( RBNode *t)
{
if( t!=t->left)
{
PrintInOrder(t->left);
cout<<t->key<<" ";
PrintInOrder(t->right);
}
}
void makeEmpty( RBNode *t)
{
if( t!=t->left)
{
makeEmpty(t->left);
makeEmpty(t->right);
delete t;
}
}
};
int main()
{
RedBlackTree<int> T;
for( int i=0; i<20; ++i)
T.insert(i);
T.print();
T.printInOrder();
int x;
while( cin>>x)
{
T.remove(x);
T.print();
T.printInOrder();
}
T.print();
return 0;
}