|
-
-
-
- // The RedBlackEntry class is an Abstract Base Class. This means that no
- // instance of the RedBlackEntry class can exist. Only classes which
- // inherit from the RedBlackEntry class can exist. Furthermore any class
- // which inherits from the RedBlackEntry class must define the member
- // function GetKey(). The Print() member function does not have to
- // be defined because a default definition exists.
- //
- // The GetKey() function should return an integer key for that entry.
- // The key for an entry should never change otherwise bad things might occur.
-
- class RedBlackEntry {
- public:
- RedBlackEntry();
- virtual ~RedBlackEntry();
- virtual int GetKey() const = 0;
- virtual void Print() const;
- };
-
- class RedBlackTreeNode {
- friend class RedBlackTree;
- public:
- void Print(RedBlackTreeNode*,
- RedBlackTreeNode*) const;
- RedBlackTreeNode();
- RedBlackTreeNode(RedBlackEntry *);
- RedBlackEntry * GetEntry() const;
- ~RedBlackTreeNode();
- protected:
- RedBlackEntry * storedEntry;
- int key;
- int red; /* if red=0 then the node is black */
- RedBlackTreeNode * left;
- RedBlackTreeNode * right;
- RedBlackTreeNode * parent;
- };
-
-
-
- class RedBlackTree {
- public:
- RedBlackTree();
- ~RedBlackTree();
- void Print() const;
- RedBlackEntry * DeleteNode(RedBlackTreeNode *);
- RedBlackTreeNode * Insert(RedBlackEntry *);
- RedBlackTreeNode * GetPredecessorOf(RedBlackTreeNode *) const;
- RedBlackTreeNode * GetSuccessorOf(RedBlackTreeNode *) const;
- RedBlackTreeNode * Search(int key);
- TemplateStack<RedBlackTreeNode *> * Enumerate(int low, int high) ;
- void CheckAssumptions() const;
- protected:
- /* A sentinel is used for root and for nil. These sentinels are */
- /* created when RedBlackTreeCreate is caled. root->left should always */
- /* point to the node which is the root of the tree. nil points to a */
- /* node which should always be black but has aribtrary children and */
- /* parent and no key or info. The point of using these sentinels is so */
- /* that the root and nil nodes do not require special cases in the code */
- RedBlackTreeNode * root;
- RedBlackTreeNode * nil;
- void LeftRotate(RedBlackTreeNode *);
- void RightRotate(RedBlackTreeNode *);
- void TreeInsertHelp(RedBlackTreeNode *);
- void TreePrintHelper(RedBlackTreeNode *) const;
- void FixUpMaxHigh(RedBlackTreeNode *);
- void DeleteFixUp(RedBlackTreeNode *);
- };
-
- const int MIN_INT=-MAX_INT;
-
- RedBlackTreeNode::RedBlackTreeNode(){
- };
-
- RedBlackTreeNode::RedBlackTreeNode(RedBlackEntry * newEntry)
- : storedEntry (newEntry) , key(newEntry->GetKey()) {
- };
-
- RedBlackTreeNode::~RedBlackTreeNode(){
- };
-
- RedBlackEntry * RedBlackTreeNode::GetEntry() const {return storedEntry;}
-
- RedBlackEntry::RedBlackEntry(){
- };
- RedBlackEntry::~RedBlackEntry(){
- };
- void RedBlackEntry::Print() const {
- cout << "No Print Method defined. Using Default: " << GetKey() << endl;
- }
-
- RedBlackTree::RedBlackTree()
- {
- nil = new RedBlackTreeNode;
- nil->left = nil->right = nil->parent = nil;
- nil->red = 0;
- nil->key = MIN_INT;
- nil->storedEntry = NULL;
-
- root = new RedBlackTreeNode;
- root->parent = root->left = root->right = nil;
- root->key = MAX_INT;
- root->red=0;
- root->storedEntry = NULL;
- }
-
- /***********************************************************************/
- /* FUNCTION: LeftRotate */
- /**/
- /* INPUTS: the node to rotate on */
- /**/
- /* OUTPUT: None */
- /**/
- /* Modifies Input: this, x */
- /**/
- /* EFFECTS: Rotates as described in _Introduction_To_Algorithms by */
- /* Cormen, Leiserson, Rivest (Chapter 14). Basically this */
- /* makes the parent of x be to the left of x, x the parent of */
- /* its parent before the rotation and fixes other pointers */
- /* accordingly. */
- /***********************************************************************/
-
- void RedBlackTree::LeftRotate(RedBlackTreeNode* x) {
- RedBlackTreeNode* y;
-
- /* I originally wrote this function to use the sentinel for */
- /* nil to avoid checking for nil. However this introduces a */
- /* very subtle bug because sometimes this function modifies */
- /* the parent pointer of nil. This can be a problem if a */
- /* function which calls LeftRotate also uses the nil sentinel */
- /* and expects the nil sentinel's parent pointer to be unchanged */
- /* after calling this function. For example, when DeleteFixUP */
- /* calls LeftRotate it expects the parent pointer of nil to be */
- /* unchanged. */
-
- y=x->right;
- x->right=y->left;
-
- if (y->left != nil) y->left->parent=x; /* used to use sentinel here */
- /* and do an unconditional assignment instead of testing for nil */
-
- y->parent=x->parent;
-
- /* instead of checking if x->parent is the root as in the book, we */
- /* count on the root sentinel to implicitly take care of this case */
- if( x == x->parent->left) {
- x->parent->left=y;
- } else {
- x->parent->right=y;
- }
- y->left=x;
- x->parent=y;
- }
-
- /***********************************************************************/
- /* FUNCTION: RighttRotate */
- /**/
- /* INPUTS: node to rotate on */
- /**/
- /* OUTPUT: None */
- /**/
- /* Modifies Input?: this, y */
- /**/
- /* EFFECTS: Rotates as described in _Introduction_To_Algorithms by */
- /* Cormen, Leiserson, Rivest (Chapter 14). Basically this */
- /* makes the parent of x be to the left of x, x the parent of */
- /* its parent before the rotation and fixes other pointers */
- /* accordingly. */
- /***********************************************************************/
-
- void RedBlackTree::RightRotate(RedBlackTreeNode* y) {
- RedBlackTreeNode* x;
-
- /* I originally wrote this function to use the sentinel for */
- /* nil to avoid checking for nil. However this introduces a */
- /* very subtle bug because sometimes this function modifies */
- /* the parent pointer of nil. This can be a problem if a */
- /* function which calls LeftRotate also uses the nil sentinel */
- /* and expects the nil sentinel's parent pointer to be unchanged */
- /* after calling this function. For example, when DeleteFixUP */
- /* calls LeftRotate it expects the parent pointer of nil to be */
- /* unchanged. */
-
- x=y->left;
- y->left=x->right;
-
- if (nil != x->right) x->right->parent=y; /*used to use sentinel here */
- /* and do an unconditional assignment instead of testing for nil */
-
- /* instead of checking if x->parent is the root as in the book, we */
- /* count on the root sentinel to implicitly take care of this case */
- x->parent=y->parent;
- if( y == y->parent->left) {
- y->parent->left=x;
- } else {
- y->parent->right=x;
- }
- x->right=y;
- y->parent=x;
- }
-
- /***********************************************************************/
- /* FUNCTION: TreeInsertHelp */
- /**/
- /* INPUTS: z is the node to insert */
- /**/
- /* OUTPUT: none */
- /**/
- /* Modifies Input: this, z */
- /**/
- /* EFFECTS: Inserts z into the tree as if it were a regular binary tree */
- /* using the algorithm described in _Introduction_To_Algorithms_ */
- /* by Cormen et al. This funciton is only intended to be called */
- /* by the Insert function and not by the user */
- /***********************************************************************/
-
- void RedBlackTree::TreeInsertHelp(RedBlackTreeNode* z) {
- /* This function should only be called by RedBlackTree::Insert */
- RedBlackTreeNode* x;
- RedBlackTreeNode* y;
-
- z->left=z->right=nil;
- y=root;
- x=root->left;
- while( x != nil) {
- y=x;
- if ( x->key > z->key) {
- x=x->left;
- } else { /* x->key <= z->key */
- x=x->right;
- }
- }
- z->parent=y;
- if ( (y == root) ||
- (y->key > z->key) ) {
- y->left=z;
- } else {
- y->right=z;
- }
- }
-
- /* Before calling InsertNode the node x should have its key set */
-
- /***********************************************************************/
- /* FUNCTION: InsertNode */
- /**/
- /* INPUTS: newEntry is the entry to insert*/
- /**/
- /* OUTPUT: This function returns a pointer to the newly inserted node */
- /* which is guarunteed to be valid until this node is deleted. */
- /* What this means is if another data structure stores this */
- /* pointer then the tree does not need to be searched when this */
- /* is to be deleted. */
- /**/
- /* Modifies Input: tree */
- /**/
- /* EFFECTS: Creates a node node which contains the appropriate key and */
- /* info pointers and inserts it into the tree. */
- /***********************************************************************/
- /* jim */
- RedBlackTreeNode * RedBlackTree::Insert(RedBlackEntry * newEntry)
- {
- RedBlackTreeNode * y;
- RedBlackTreeNode * x;
- RedBlackTreeNode * newNode;
-
- x = new RedBlackTreeNode(newEntry);
- TreeInsertHelp(x);
- newNode = x;
- x->red=1;
- while(x->parent->red) { /* use sentinel instead of checking for root */
- if (x->parent == x->parent->parent->left) {
- y=x->parent->parent->right;
- if (y->red) {
- x->parent->red=0;
- y->red=0;
- x->parent->parent->red=1;
- x=x->parent->parent;
- } else {
- if (x == x->parent->right) {
- x=x->parent;
- LeftRotate(x);
- }
- x->parent->red=0;
- x->parent->parent->red=1;
- RightRotate(x->parent->parent);
- }
- } else { /* case for x->parent == x->parent->parent->right */
- /* this part is just like the section above with */
- /* left and right interchanged */
- y=x->parent->parent->left;
- if (y->red) {
- x->parent->red=0;
- y->red=0;
- x->parent->parent->red=1;
- x=x->parent->parent;
- } else {
- if (x == x->parent->left) {
- x=x->parent;
- RightRotate(x);
- }
- x->parent->red=0;
- x->parent->parent->red=1;
- LeftRotate(x->parent->parent);
- }
- }
- }
- root->left->red=0;
- return(newNode);
- }
-
- /***********************************************************************/
- /* FUNCTION: GetSuccessorOf */
- /**/
- /* INPUTS: x is the node we want the succesor of */
- /**/
- /* OUTPUT: This function returns the successor of x or NULL if no */
- /* successor exists. */
- /**/
- /* Modifies Input: none */
- /**/
- /* Note: uses the algorithm in _Introduction_To_Algorithms_ */
- /***********************************************************************/
-
- RedBlackTreeNode * RedBlackTree::GetSuccessorOf(RedBlackTreeNode * x) const
- {
- RedBlackTreeNode* y;
-
- if (nil != (y = x->right)) { /* assignment to y is intentional */
- while(y->left != nil) { /* returns the minium of the right subtree of x */
- y=y->left;
- }
- return(y);
- } else {
- y=x->parent;
- while(x == y->right) { /* sentinel used instead of checking for nil */
- x=y;
- y=y->parent;
- }
- if (y == root) return(nil);
- return(y);
- }
- }
-
- /***********************************************************************/
- /* FUNCTION: GetPredecessorOf */
- /**/
- /* INPUTS: x is the node to get predecessor of */
- /**/
- /* OUTPUT: This function returns the predecessor of x or NULL if no */
- /* predecessor exists. */
- /**/
- /* Modifies Input: none */
- /**/
- /* Note: uses the algorithm in _Introduction_To_Algorithms_ */
- /***********************************************************************/
-
- RedBlackTreeNode * RedBlackTree::GetPredecessorOf(RedBlackTreeNode * x) const {
- RedBlackTreeNode* y;
-
- if (nil != (y = x->left)) { /* assignment to y is intentional */
- while(y->right != nil) { /* returns the maximum of the left subtree of x */
- y=y->right;
- }
- return(y);
- } else {
- y=x->parent;
- while(x == y->left) {
- if (y == root) return(nil);
- x=y;
- y=y->parent;
- }
- return(y);
- }
- }
-
- /***********************************************************************/
- /* FUNCTION: Print */
- /**/
- /* INPUTS: none */
- /**/
- /* OUTPUT: none */
- /**/
- /* EFFECTS: This function recursively prints the nodes of the tree */
- /* inorder. */
- /**/
- /* Modifies Input: none */
- /**/
- /* Note: This function should only be called from ITTreePrint */
- /***********************************************************************/
-
- void RedBlackTreeNode::Print(RedBlackTreeNode * nil,
- RedBlackTreeNode * root) const {
- storedEntry->Print();
- printf(", key=%i ",key);
- printf(" l->key=");
- if( left == nil) printf("NULL"); else printf("%i",left->key);
- printf(" r->key=");
- if( right == nil) printf("NULL"); else printf("%i",right->key);
- printf(" p->key=");
- if( parent == root) printf("NULL"); else printf("%i",parent->key);
- printf(" red=%i\n",red);
- }
-
- void RedBlackTree::TreePrintHelper( RedBlackTreeNode* x) const {
-
- if (x != nil) {
- TreePrintHelper(x->left);
- x->Print(nil,root);
- TreePrintHelper(x->right);
- }
- }
-
- /***********************************************************************/
- /* FUNCTION: Print */
- /**/
- /* INPUTS: none */
- /**/
- /* OUTPUT: none */
- /**/
- /* EFFECT: This function recursively prints the nodes of the tree */
- /* inorder. */
- /**/
- /* Modifies Input: none */
- /**/
- /***********************************************************************/
-
- void RedBlackTree::Print() const {
- TreePrintHelper(root->left);
- }
-
- /***********************************************************************/
- /* FUNCTION: DeleteFixUp */
- /**/
- /* INPUTS: x is the child of the spliced */
- /* out node in DeleteNode. */
- /**/
- /* OUTPUT: none */
- /**/
- /* EFFECT: Performs rotations and changes colors to restore red-black */
- /* properties after a node is deleted */
- /**/
- /* Modifies Input: this, x */
- /**/
- /* The algorithm from this function is from _Introduction_To_Algorithms_ */
- /***********************************************************************/
-
- void RedBlackTree::DeleteFixUp(RedBlackTreeNode* x) {
- RedBlackTreeNode * w;
- RedBlackTreeNode * rootLeft = root->left;
-
- while( (!x->red) && (rootLeft != x)) {
- if (x == x->parent->left) {
-
- //
- w=x->parent->right;
- if (w->red) {
- w->red=0;
- x->parent->red=1;
- LeftRotate(x->parent);
- w=x->parent->right;
- }
- if ( (!w->right->red) && (!w->left->red) ) {
- w->red=1;
- x=x->parent;
- } else {
- if (!w->right->red) {
- w->left->red=0;
- w->red=1;
- RightRotate(w);
- w=x->parent->right;
- }
- w->red=x->parent->red;
- x->parent->red=0;
- w->right->red=0;
- LeftRotate(x->parent);
- x=rootLeft; /* this is to exit while loop */
- }
- //
-
- } else { /* the code below is has left and right switched from above */
- w=x->parent->left;
- if (w->red) {
- w->red=0;
- x->parent->red=1;
- RightRotate(x->parent);
- w=x->parent->left;
- }
- if ( (!w->right->red) && (!w->left->red) ) {
- w->red=1;
- x=x->parent;
- } else {
- if (!w->left->red) {
- w->right->red=0;
- w->red=1;
- LeftRotate(w);
- w=x->parent->left;
- }
- w->red=x->parent->red;
- x->parent->red=0;
- w->left->red=0;
- RightRotate(x->parent);
- x=rootLeft; /* this is to exit while loop */
- }
- }
- }
- x->red=0;
-
- }
-
-
- /***********************************************************************/
- /* FUNCTION: DeleteNode */
- /**/
- /* INPUTS: tree is the tree to delete node z from */
- /**/
- /* OUTPUT: returns the RedBlackEntry stored at deleted node */
- /**/
- /* EFFECT: Deletes z from tree and but don't call destructor */
- /**/
- /* Modifies Input: z */
- /**/
- /* The algorithm from this function is from _Introduction_To_Algorithms_ */
- /***********************************************************************/
-
- RedBlackEntry * RedBlackTree::DeleteNode(RedBlackTreeNode * z){
- RedBlackTreeNode* y;
- RedBlackTreeNode* x;
- RedBlackEntry * returnValue = z->storedEntry;
-
- y= ((z->left == nil) || (z->right == nil)) ? z : GetSuccessorOf(z);
- x= (y->left == nil) ? y->right : y->left;
- if (root == (x->parent = y->parent)) { /* assignment of y->p to x->p is intentional */
- root->left=x;
- } else {
- if (y == y->parent->left) {
- y->parent->left=x;
- } else {
- y->parent->right=x;
- }
- }
- if (y != z) { /* y should not be nil in this case */
-
- /* y is the node to splice out and x is its child */
-
- y->left=z->left;
- y->right=z->right;
- y->parent=z->parent;
- z->left->parent=z->right->parent=y;
- if (z == z->parent->left) {
- z->parent->left=y;
- } else {
- z->parent->right=y;
- }
- if (!(y->red)) {
- y->red = z->red;
- DeleteFixUp(x);
- } else
- y->red = z->red;
- delete z;
- } else {
- if (!(y->red)) DeleteFixUp(x);
- delete y;
- }
- return returnValue;
- }
-
-
- /***********************************************************************/
- /* FUNCTION: Enumerate */
- /**/
- /* INPUTS: tree is the tree to look for keys between [low,high] */
- /**/
- /* OUTPUT: stack containing pointers to the nodes between [low,high] */
- /**/
- /* Modifies Input: none */
- /**/
- /* EFFECT: Returns a stack containing pointers to nodes containing */
- /* keys which in [low,high]/ */
- /**/
- /***********************************************************************/
-
- TemplateStack<RedBlackTreeNode *> * RedBlackTree::Enumerate(int low,
- int high) {
- TemplateStack<RedBlackTreeNode *> * enumResultStack =
- new TemplateStack<RedBlackTreeNode *>(4);
-
- RedBlackTreeNode* x=root->left;
- RedBlackTreeNode* lastBest=NULL;
-
- while(nil != x) {
- if ( x->key > high ) {
- x=x->left;
- } else {
- lastBest=x;
- x=x->right;
- }
- }
- while ( (lastBest) && (low <= lastBest->key) ) {
- enumResultStack->Push(lastBest);
- lastBest=GetPredecessorOf(lastBest);
- }
- return(enumResultStack);
- }
|