Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members

RedBlackTree.h

Go to the documentation of this file.
00001 #ifndef MMANN_CPP_REDBLACK_H
00002 #define MMANN_CPP_REDBLACK_H
00003 
00011 
00012 #include <stdlib.h>
00013 #include <assert.h>
00014 #include "CompareAlgorithms.h"
00015 #include "RedBlackNode.h"
00016 #include "AGenericTree.h"
00017 
00019 enum RedBlackTreeLookup {RBNONE = -1, RBEQUAL = 0, RBGTEQ, RBLTEQ, RBLESS, RBGREAT, RBNEXT, RBPREV, RBFIRST, RBLAST};
00020 
00037 template <class Data, class ConfigData>
00038 class RedBlackTree : public AGenericTree<Data, ConfigData>
00039 {
00040 public:
00042     RedBlackTree(ACompareNodesAlgorithm<Data, ConfigData>* Compare, DeleteTreeDataEnum DeleteTreeData = NO_DELETE_TREE_ITEM,
00043                  ConfigData* pConfigData = NULL);
00044     
00046     ~RedBlackTree();
00047 
00053     virtual Data* Search(Data* NodeData, bool* NodeInserted);
00054 
00059     virtual Data* Find(Data* NodeData);
00060 
00065     Data* Lookup(RedBlackTreeLookup Mode, Data* NodeData);
00066 
00071     Data* Delete(Data* NodeData);
00072 
00073 protected:
00074 
00081     RedBlackNode<Data>* Traverse(bool Insert, Data* NodeData, bool* NodeInserted);
00082 
00087     void DeleteNode(RedBlackNode<Data>** Root, RedBlackNode<Data>* Node);
00088 
00093     void DeleteNodeFix(RedBlackNode<Data>** Root, RedBlackNode<Data>* Node);
00094 
00099     void LeftRotate(RedBlackNode<Data>** Root, RedBlackNode<Data>* x);
00100 
00105     void RightRotate(RedBlackNode<Data>** Root, RedBlackNode<Data>* y);
00110     RedBlackNode<Data>* GetSuccessor(const RedBlackNode<Data>* Node);
00111 
00116     RedBlackNode<Data>* GetPredecessor(const RedBlackNode<Data>* Node);
00117 
00119     RedBlackNode<Data>* m_Root;
00120 };
00121 
00122 template <class Data, class ConfigData>
00123 RedBlackTree<Data, ConfigData>::RedBlackTree(ACompareNodesAlgorithm<Data, ConfigData>* Compare, DeleteTreeDataEnum DeleteTreeData,
00124                  ConfigData* pConfigData) : AGenericTree<Data, ConfigData>(Compare, DeleteTreeData, pConfigData)
00125 {
00126     m_Root = NULL;
00127 }
00128 
00129 template <class Data, class ConfigData>
00130 RedBlackTree<Data, ConfigData>::~RedBlackTree()
00131 {
00132     if (m_Root != NULL)
00133         DeleteAllRedBlackNodes(m_Root, m_DeleteTreeData);
00134 }
00135 
00136 template <class Data, class ConfigData>
00137 Data* RedBlackTree<Data, ConfigData>::Search(Data* NodeData, bool* NodeInserted)
00138 {
00139     RedBlackNode<Data>* Node = Traverse(true, NodeData, NodeInserted);
00140 
00141     return ((*NodeInserted) ? NULL : Node->m_Data);
00142 }
00143 
00144 template <class Data, class ConfigData>
00145 Data* RedBlackTree<Data, ConfigData>::Find(Data* NodeData)
00146 {
00147     RedBlackNode<Data>* x;
00148     bool DummyIsInsert;
00149     
00150     //if we have an empty tree, return
00151     if (m_Root == NULL)
00152         return NULL;
00153 
00154     x = Traverse(false, NodeData, &DummyIsInsert);
00155 
00156     return (x == NULL ? NULL : x->m_Data);
00157 }
00158 
00159 template <class Data, class ConfigData>
00160 Data* RedBlackTree<Data, ConfigData>::Lookup(RedBlackTreeLookup Mode, Data* NodeData)
00161 {
00162     if (m_Root == NULL)
00163         return NULL;
00164 
00165     RedBlackNode<Data> *x, *y;
00166     int CompareValue;
00167     bool Found = false;
00168 
00169     y = NULL;
00170     x = m_Root;
00171 
00172     if (Mode == RBFIRST)
00173     {
00174         //keep going until you hit NULL
00175         while (x != NULL)
00176         {
00177             y = x;
00178             x = x->m_Left;
00179         }
00180 
00181         return y->m_Data;
00182     }
00183     else if (Mode == RBLAST)
00184     {
00185         //keep going until you hit NULL
00186         while (x != NULL)
00187         {
00188             y = x;
00189             x = x->m_Right;
00190         }
00191 
00192         return y->m_Data;
00193     }
00194 
00195     //walk x down the tree
00196     while ((x != NULL) && (!Found))
00197     {
00198         y=x;
00199         CompareValue = m_CompareNodes->Compare(NodeData, x->m_Data, m_ConfigData);
00200         if (CompareValue < 0)
00201             x = x->m_Left;
00202         else if (CompareValue > 0)
00203             x = x->m_Right;
00204         else
00205             Found = true;
00206     }
00207 
00208     if (Found && (Mode == RBEQUAL || Mode == RBGTEQ || Mode == RBLTEQ))
00209         return x->m_Data;
00210 
00211     if (!Found && (Mode == RBEQUAL || Mode == RBNEXT || Mode == RBPREV))
00212         return NULL;
00213 
00214     if ((Mode == RBGTEQ) || (!Found && Mode == RBGREAT))
00215     {
00216         if (CompareValue > 0)
00217             return GetSuccessor(y)->m_Data;
00218         else
00219             return y->m_Data;
00220     }
00221 
00222     if ((Mode == RBLTEQ) || (!Found && Mode == RBLESS))
00223     {
00224         if (CompareValue < 0)
00225             return GetPredecessor(y)->m_Data;
00226         else
00227             return y->m_Data;
00228     }
00229 
00230     if ((Mode == RBNEXT) || (Found && Mode == RBGREAT))
00231     {
00232         RedBlackNode<Data>* Dummy = GetSuccessor(x);
00233         if (Dummy != NULL)
00234             return Dummy->m_Data;
00235         return NULL;
00236     }
00237     if ((Mode == RBPREV) || (Found && Mode == RBLESS))
00238     {
00239         RedBlackNode<Data>* Dummy = GetPredecessor(x);
00240         if (Dummy != NULL)
00241             return Dummy->m_Data;
00242         return NULL;
00243     }
00244 
00245     //all cases should be covered
00246     assert(false);
00247     return NULL;
00248 }
00249 
00250 template <class Data, class ConfigData>
00251 RedBlackNode<Data>* RedBlackTree<Data, ConfigData>::Traverse(bool Insert, Data* NodeData, bool* NodeInserted)
00252 {
00253     *NodeInserted = false;
00254     RedBlackNode<Data> *x, *y, *z;
00255     int CompareValue;
00256     bool Found = false;
00257 
00258     y = NULL;
00259     x = m_Root;
00260 
00261     //walk x down the tree
00262     while ((x != NULL) && (!Found))
00263     {
00264         y = x;
00265 
00266         CompareValue = m_CompareNodes->Compare(NodeData, x->m_Data, m_ConfigData);
00267 
00268         if (CompareValue < 0)
00269             x = x->m_Left;
00270         else if (CompareValue > 0)
00271             x = x->m_Right;
00272         else
00273             Found = true;
00274     }
00275 
00276     if (Found || !Insert)
00277         return x;
00278 
00279     z = new RedBlackNode<Data>(NodeData);
00280     *NodeInserted = true;
00281     z->m_Up = y;
00282     
00283     if (y == NULL)
00284         m_Root = z;
00285     else
00286     {
00287         CompareValue = m_CompareNodes->Compare(z->m_Data, y->m_Data, m_ConfigData);
00288         if (CompareValue < 0)
00289             y->m_Left = z;
00290         else
00291             y->m_Right = z;
00292     }
00293 
00294     z->m_Left = NULL;
00295     z->m_Right = NULL;
00296 
00297     //color new node red
00298     z->m_Color = RED;
00299 
00300     // Having added a red node, we must now walk back up the tree balancing
00301     // it, by a series of rotations and changing of colours
00302     x=z;
00303 
00304     // While we are not at the top and our parent node is red
00305     // N.B. Since the root node is garanteed black, then we
00306     // are also going to stop if we are the child of the root
00307 
00308     while ((x != m_Root) && (x->m_Up->m_Color == RED))
00309     {
00310         //if our parent is on the left side of our grandparent
00311         if (x->m_Up == x->m_Up->m_Up->m_Left)
00312         {
00313             //get the right side of our grandparent
00314             y = x->m_Up->m_Up->m_Right;
00315             if ((y != NULL) && (y->m_Color == RED))
00316             {
00317                 //make parent black
00318                 x->m_Up->m_Color = BLACK;
00319                 //make uncle black
00320                 y->m_Color = BLACK;
00321                 //make grandparent red
00322                 x->m_Up->m_Up->m_Color = RED;
00323                 //now consider grandparent
00324                 x = x->m_Up->m_Up;
00325             }
00326             else
00327             {
00328                 //if we are on the right side of parent
00329                 if (x == x->m_Up->m_Right)
00330                 {
00331                     //move up parent
00332                     x = x->m_Up;
00333                     LeftRotate(&m_Root, x);
00334                 }
00335 
00336                 //make parent black
00337                 x->m_Up->m_Color = BLACK;
00338                 //make grandparent red
00339                 x->m_Up->m_Up->m_Color = RED;
00340                 //right rotate grandparent
00341                 RightRotate(&m_Root, x->m_Up->m_Up);
00342             }
00343         }
00344         else
00345         {
00346             //everything here is same as above, just exchange left for right
00347             y = x->m_Up->m_Up->m_Left;
00348             if ((y != NULL) && (y->m_Color == RED))
00349             {
00350                 //make parent black
00351                 x->m_Up->m_Color = BLACK;
00352                 //make uncle black
00353                 y->m_Color = BLACK;
00354                 //make grandparent red
00355                 x->m_Up->m_Up->m_Color = RED;
00356                 //now consider grandparent
00357                 x = x->m_Up->m_Up;
00358             }
00359             else
00360             {
00361                 //if we are on the right side of parent
00362                 if (x == x->m_Up->m_Left)
00363                 {
00364                     //move up parent
00365                     x = x->m_Up;
00366                     RightRotate(&m_Root, x);
00367                 }
00368 
00369                 //make parent black
00370                 x->m_Up->m_Color = BLACK;
00371                 //make grandparent red
00372                 x->m_Up->m_Up->m_Color = RED;
00373                 //right rotate grandparent
00374                 LeftRotate(&m_Root, x->m_Up->m_Up);
00375             }
00376         }
00377     }
00378 
00379     //set the root node black
00380     m_Root->m_Color = BLACK;
00381 
00382     return z;
00383 }
00384 
00385 template <class Data, class ConfigData>
00386 Data* RedBlackTree<Data, ConfigData>::Delete(Data* NodeData)
00387 {
00388     RedBlackNode<Data> *x;
00389     Data* y;
00390     bool DummyIsInsert;
00391 
00392     x = Traverse(false, NodeData, &DummyIsInsert);
00393 
00394     if (x == NULL)
00395         return NULL;
00396 
00397     y = x->m_Data;
00398 
00399     DeleteNode(&m_Root, x);
00400 
00401     return y;
00402 }
00403 
00404 template <class Data, class ConfigData>
00405 void RedBlackTree<Data, ConfigData>::DeleteNode(RedBlackNode<Data>** Root, RedBlackNode<Data>* Node)
00406 {
00407     RedBlackNode<Data> *x,
00408                       *y;
00409 
00410     if ((Node->m_Left == NULL) || (Node->m_Right == NULL))
00411         y = Node;
00412     else
00413         y = GetSuccessor(Node);
00414 
00415     if (y->m_Left != NULL)
00416         x = y->m_Left;
00417     else
00418         x = y->m_Right;
00419 
00420     if (x != NULL)
00421         x->m_Up = y->m_Up;
00422 
00423     if (y->m_Up == NULL)
00424     {
00425         *Root = x;
00426     }
00427     else
00428     {
00429         if (y == y->m_Up->m_Left)
00430             y->m_Up->m_Left = x;
00431         else
00432             y->m_Up->m_Right = x;
00433     }
00434 
00435     if (y != Node)
00436         Node->m_Data = y->m_Data;
00437 
00438     if (y->m_Color == BLACK)
00439         DeleteNodeFix(Root, x);
00440 
00441     delete y;
00442 }
00443 
00444 template <class Data, class ConfigData>
00445 void RedBlackTree<Data, ConfigData>::DeleteNodeFix(RedBlackNode<Data>** Root, RedBlackNode<Data>* Node)
00446 {
00447     RedBlackNode<Data> *w;
00448 
00449     while ((Node != *Root) && (Node != NULL) && (Node->m_Color == BLACK))
00450     {
00451         if (Node == Node->m_Up->m_Left)
00452         {
00453             w = Node->m_Up->m_Right;
00454             if (w->m_Color == RED)
00455             {
00456                 w->m_Color = BLACK;
00457                 Node->m_Up->m_Color = RED;
00458                 LeftRotate(Root, Node->m_Up);
00459                 w = Node->m_Up->m_Right;
00460             }
00461 
00462             if ((w->m_Left->m_Color == BLACK) && 
00463                 (w->m_Right->m_Color == BLACK))
00464             {
00465                 w->m_Color = RED;
00466                 Node = Node->m_Up;
00467             }
00468             else
00469             {
00470                 if (w->m_Right->m_Color == BLACK)
00471                 {
00472                     w->m_Left->m_Color = BLACK;
00473                     w->m_Color = RED;
00474                     RightRotate(Root, w);
00475                     w = Node->m_Up->m_Right;
00476                 }
00477 
00478                 w->m_Color = Node->m_Up->m_Color;
00479                 Node->m_Up->m_Color = BLACK;
00480                 w->m_Right->m_Color = BLACK;
00481                 LeftRotate(Root, Node->m_Up);
00482                 Node = *Root;
00483             }
00484 
00485         }
00486         else
00487         {
00488             w = Node->m_Up->m_Left;
00489             if (w->m_Color == RED)
00490             {
00491                 w->m_Color = BLACK;
00492                 Node->m_Up->m_Color = RED;
00493                 RightRotate(Root, Node->m_Up);
00494                 w = Node->m_Up->m_Left;
00495             }
00496 
00497             if ((w->m_Right->m_Color == BLACK) && 
00498                 (w->m_Left->m_Color == BLACK))
00499             {
00500                 w->m_Color = RED;
00501                 Node = Node->m_Up;
00502             }
00503             else
00504             {
00505                 if (w->m_Left->m_Color == BLACK)
00506                 {
00507                     w->m_Right->m_Color = BLACK;
00508                     w->m_Color = RED;
00509                     LeftRotate(Root, w);
00510                     w = Node->m_Up->m_Left;
00511                 }
00512 
00513                 w->m_Color = Node->m_Up->m_Color;
00514                 Node->m_Up->m_Color = BLACK;
00515                 w->m_Left->m_Color = BLACK;
00516                 RightRotate(Root, Node->m_Up);
00517                 Node = *Root;
00518             }
00519         }
00520     }
00521 
00522     if (Node != NULL)
00523         Node->m_Color = BLACK;
00524 }
00525 
00526 /*
00527 ** Rotate our tree thus:-
00528 **
00529 **             X        LeftRotate(Node)--->             Y
00530 **           /   \                                     /   \
00531 **          A     Y    <---RightRotate(Node)          X    C
00532 **              /   \                               /   \
00533 **             B     C                             A     B
00534 **
00535 ** N.B. This does not change the ordering.
00536 **
00537 ** We assume that Node is not NULL
00538 */
00539 template <class Data, class ConfigData>
00540 void RedBlackTree<Data, ConfigData>::LeftRotate(RedBlackNode<Data>** Root, RedBlackNode<Data>* x)
00541 {
00542     RedBlackNode<Data> *y;
00543 
00544     assert(x != NULL);
00545     assert(x->m_Right != NULL);
00546 
00547     y = x->m_Right; //set Y
00548 
00549     //turn Y's left subtree into node's right subtree (move B)
00550     x->m_Right = y->m_Left;
00551 
00552     //if B is not NULL, set its parent to be X
00553     if (y->m_Left != NULL)
00554         y->m_Left->m_Up = x;
00555 
00556     // set Y's parent to be what X's parent was
00557     y->m_Up = x->m_Up;
00558 
00559     //if X was the root
00560     if (x->m_Up == NULL)
00561     {
00562         *Root = y;
00563     }
00564     else
00565     {
00566         //set X's parent left or right pointer to Y
00567         if (x == x->m_Up->m_Left)
00568             x->m_Up->m_Left = y;
00569         else
00570             x->m_Up->m_Right = y;
00571     }
00572 
00573     //put X on Y's left
00574     y->m_Left = x;
00575     
00576     //set X's parent to be Y
00577     x->m_Up = y;
00578 
00579 }
00580 
00581 template <class Data, class ConfigData>
00582 void RedBlackTree<Data, ConfigData>::RightRotate(RedBlackNode<Data>** Root, RedBlackNode<Data>* y)
00583 {
00584     RedBlackNode<Data> *x;
00585 
00586     assert(y != NULL);
00587     assert(y->m_Left != NULL);
00588 
00589     x = y->m_Left; //set x
00590 
00591     // Turn X's right subtree into Y's left subtree (move B) 
00592     y->m_Left = x->m_Right;
00593 
00594     /* If B is not null, set it's parent to be Y */
00595     if (x->m_Right != NULL)
00596         x->m_Right->m_Up = y;
00597 
00598     /* Set X's parent to be what Y's parent was */
00599     x->m_Up = y->m_Up;
00600 
00601     /* if Y was the root */
00602     if (y->m_Up == NULL)
00603     {
00604         *Root = x;
00605     }
00606     else
00607     {
00608         /* Set Y's parent's left or right pointer to be X */
00609         if (y == y->m_Up->m_Left)
00610         {
00611             y->m_Up->m_Left = x;
00612         }
00613         else
00614         {
00615             y->m_Up->m_Right = x;
00616         }
00617     }
00618 
00619     /* Put Y on X's right */
00620     x->m_Right = y;
00621 
00622     /* Set Y's parent to be X */
00623     y->m_Up = x;
00624 }
00625 
00626 template <class Data, class ConfigData>
00627 RedBlackNode<Data>* RedBlackTree<Data, ConfigData>::GetSuccessor(const RedBlackNode<Data>* Node)
00628 {
00629     RedBlackNode<Data> *y;
00630 
00631     if (Node->m_Right != NULL)
00632     {
00633         // If right is not NULL then go right one and then keep going left until 
00634         // we find a node with no left pointer.
00635         for (y = Node->m_Right; y->m_Left != NULL; y = y->m_Left);
00636     }
00637     else
00638     {
00639         // Go up the tree until we get to a node that is on the
00640         // left of its parent (or the root) and then return the parent
00641         y = Node->m_Up;
00642         while ((y != NULL) && (Node == y->m_Right))
00643         {
00644             Node = y;
00645             y = y->m_Up;
00646         }
00647     }
00648 
00649     return y;
00650 }
00651 
00652 template <class Data, class ConfigData>
00653 RedBlackNode<Data>* RedBlackTree<Data, ConfigData>::GetPredecessor(const RedBlackNode<Data>* Node)
00654 {
00655     RedBlackNode<Data> *y;
00656 
00657     if (Node->m_Left != NULL)
00658     {
00659         // If left is not NULL then go left one and 
00660         //then keep going right until we find a node with no right pointer.
00661         for (y = Node->m_Left; y->m_Right != NULL; y = y->m_Right);
00662     }
00663     else
00664     {
00665         /* Go up the tree until we get to a node that is on the
00666         ** right of its parent (or the root) and then return the
00667         ** parent.
00668         */
00669         y = Node->m_Up;
00670         while ((y != NULL) && (Node == y->m_Left))
00671         {
00672             Node = y;
00673             y = y->m_Up;
00674         }
00675     }
00676 
00677     return y;
00678 }
00679 
00680 #endif

Generated on Sat Nov 5 11:20:16 2005 for Cpp Freecell Solver by  doxygen 1.4.4