123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640 |
- #include "RedBlackTree.h"
- #include <limits>
- #include "PtrList.h"
- #ifdef min
- #undef min
- #endif
- #ifdef max
- #undef max
- #endif
- void RedBlackTreeIterator::next()
- {
- if (node)
- node = tree->GetSuccessorOf(node);
- }
- bool RedBlackTreeIterator::get(RedBlackTreeIterator::val_t *val)
- {
- if (node)
- {
- *val = node->GetEntry();
- return true;
- }
- return false;
- }
- RedBlackTreeNode::RedBlackTreeNode()
- {
- }
- RedBlackTreeNode::RedBlackTreeNode(key_t _key, val_t newEntry)
- : storedEntry(newEntry) , key(_key)
- {
- }
- RedBlackTreeNode::~RedBlackTreeNode()
- {
- }
- RedBlackTreeNode::val_t RedBlackTreeNode::GetEntry() const
- {
- return storedEntry;
- }
- RedBlackTree::RedBlackTree()
- {
- nil = new RedBlackTreeNode;
- nil->left = nil->right = nil->parent = nil;
- nil->red = 0;
- nil->key = std::numeric_limits<key_t>::min();
- nil->storedEntry = NULL;
- root = new RedBlackTreeNode;
- root->parent = root->left = root->right = nil;
- root->key = std::numeric_limits<key_t>::max();
- root->red=0;
- root->storedEntry = NULL;
- numElements = 0;
- }
- RedBlackTreeIterator RedBlackTree::end()
- {
- RedBlackTreeIterator temp;
- return temp;
- }
- RedBlackTreeIterator RedBlackTree::begin()
- {
- return RedBlackTreeIterator(root->left, this);
- }
- /***********************************************************************/
- /* 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;
- #ifdef CHECK_RB_TREE_ASSUMPTIONS
- CheckAssumptions();
- #elif defined(DEBUG_ASSERT)
- Assert(!nil->red,"nil not red in RedBlackTree::LeftRotate");
- #endif
- }
- /***********************************************************************/
- /* 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;
- #ifdef CHECK_RB_TREE_ASSUMPTIONS
- CheckAssumptions();
- #elif defined(DEBUG_ASSERT)
- Assert(!nil->red,"nil not red in RedBlackTree::RightRotate");
- #endif
- }
- /***********************************************************************/
- /* 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;
- }
- #if defined(DEBUG_ASSERT)
- Assert(!nil->red,"nil not red in RedBlackTree::TreeInsertHelp");
- #endif
- }
- RedBlackTreeIterator RedBlackTree::Search(key_t key)
- {
- RedBlackTreeNode* x;
- x=root->left;
- while (x != nil)
- {
- if (x->key > key)
- {
- x=x->left;
- }
- else if (x->key < key)
- {
- x=x->right;
- }
- else
- {
- return RedBlackTreeIterator(x, this);
- }
- }
- return end();
- }
- /* 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. */
- /***********************************************************************/
- RedBlackTreeIterator RedBlackTree::Insert(key_t _key, val_t newEntry)
- {
- RedBlackTreeNode * y;
- RedBlackTreeNode * x;
- RedBlackTreeNode * newNode;
- x = new RedBlackTreeNode(_key, 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;
- numElements++;
- return RedBlackTreeIterator(newNode, this);
- #ifdef CHECK_RB_TREE_ASSUMPTIONS
- CheckAssumptions();
- #elif defined(DEBUG_ASSERT)
- Assert(!nil->red,"nil not red in RedBlackTree::Insert");
- Assert(!root->red,"root not red in RedBlackTree::Insert");
- #endif
- }
- RedBlackTree::~RedBlackTree()
- {
- RedBlackTreeNode * x = root->left;
- nu::PtrList<RedBlackTreeNode> stuffToFree;
- if (x != nil)
- {
- if (x->left != nil)
- {
- stuffToFree.push_back(x->left);
- }
- if (x->right != nil)
- {
- stuffToFree.push_back(x->right);
- }
- // delete x->storedEntry;
- delete x;
- while (!stuffToFree.empty())
- {
- x = stuffToFree.back();
- stuffToFree.pop_back();
- if (x->left != nil)
- {
- stuffToFree.push_back(x->left);
- }
- if (x->right != nil)
- {
- stuffToFree.push_back(x->right);
- }
- // delete x->storedEntry;
- delete x;
- }
- }
- delete nil;
- delete root;
- }
- 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;
- #ifdef CHECK_RB_TREE_ASSUMPTIONS
- CheckAssumptions();
- #elif defined(DEBUG_ASSERT)
- Assert(!nil->red,"nil not black in RedBlackTree::DeleteFixUp");
- #endif
- }
- void RedBlackTree::Delete(RedBlackTree::key_t key)
- {
- RedBlackTreeIterator itr = Search(key);
- DeleteNode(itr.node);
- }
- /***********************************************************************/
- /* 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_ */
- /***********************************************************************/
- RedBlackTree::val_t RedBlackTree::DeleteNode(RedBlackTreeNode * z)
- {
- RedBlackTreeNode* y;
- RedBlackTreeNode* x;
- val_t 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 */
- {
- #ifdef DEBUG_ASSERT
- Assert((y!=nil),"y is nil in DeleteNode \n");
- #endif
- /* 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;
- #ifdef CHECK_RB_TREE_ASSUMPTIONS
- CheckAssumptions();
- #elif defined(DEBUG_ASSERT)
- Assert(!nil->red,"nil not black in RedBlackTree::Delete");
- #endif
- }
- else
- {
- if (!(y->red)) DeleteFixUp(x);
- delete y;
- #ifdef CHECK_RB_TREE_ASSUMPTIONS
- CheckAssumptions();
- #elif defined(DEBUG_ASSERT)
- Assert(!nil->red,"nil not black in RedBlackTree::Delete");
- #endif
- }
- numElements--;
- return returnValue;
- }
- size_t RedBlackTree::size() const
- {
- return numElements;
- }
- /***********************************************************************/
- /* 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: 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);
- }
- }
|