Advertisement
Guest User

Untitled

a guest
Aug 2nd, 2015
264
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 28.44 KB | None | 0 0
  1. #ifdef CMPT225RBTREE
  2.  
  3. /*
  4.    
  5.     CMPT 225 D2 Summer 2014  --- Assignment 4 (RedBlack Tree)
  6.    
  7.     Student:    Echo Liu
  8.     Professor:  John Edgar
  9.  
  10.     Class: RedBlack Tree
  11.  
  12.     Description:
  13.         Before we describe what a red black tree is we must go over briefly what a binary search tree is. A binary
  14.         search tree or BST for short is a tree in which each node has at most two children with the left and right children having
  15.         the following set of properties.
  16.             1. The children themselves are roots of their own subtrees
  17.             2. The left child and its associated subtree is less than the "main" root of the whole tree
  18.             3. The right child and its associated subtree is greater than the "main" root of the whole tree
  19.         The order the keys inserted into the BST affect the shape of the tree, if the keys come in sorted order
  20.         then the tree becomes anaemic closely resembling a linear chain of nodes forcing its performance to be O(n) instead of
  21.         O(logn).
  22.  
  23.         A Red Black tree is a variation of a binary search tree in which preserves the logarithmic height of a binary search tree
  24.         by colouring a node red or black and also imposing the following set of properties to make the tree approximately balanced.
  25.             1. No consecutive red nodes are allowed along any path.
  26.             2. The root is always black
  27.             3. Every red node has two black children
  28.             4. The amount of black nodes from the root to any descendent leaves on a simple path are equal, the root does
  29.             not get factored into the calculation this calculation is the black height.
  30.             5. Consecutive black nodes along a path are allowed
  31.  
  32.  
  33.     Prof: John Edgar
  34.  
  35.  
  36. */
  37. #include <iostream>
  38. #include <string>
  39. //#include "RedBlackTree.h"
  40. using namespace std;
  41.  
  42.  
  43. /*
  44.     Start of Node constructors
  45. */
  46.  
  47. /* This constructor takes a datum as its parameter and initializes its parent, left, and right pointer to the default NULL as well
  48.     and isBlack to true false i.e red
  49. */
  50. template <class T>
  51. Node<T>::Node(T Tdata)
  52. {
  53.     data = Tdata;
  54.     parent = NULL;
  55.     left = NULL;
  56.     right = NULL;
  57.     isBlack = false;
  58. }
  59. /*
  60.     This constructor takes in a datum and three node pointers as its parameters. The
  61.     three parameters represent left, right, and parent respectively and the default colour to red [false]
  62. */
  63. template <class T>
  64. Node<T>::Node(T Tdata, Node* pL, Node *pR, Node* pParent)
  65. {
  66.     data = Tdata;
  67.     parent = pParent;
  68.     left = pL;
  69.     right = pR;
  70.     isBlack = false;
  71. }
  72. /*
  73.     Node constructor that has four parameters
  74.     that takes in a datum, three node pointers and a colour which is denoted by a boolean flag
  75.     the three node pointers represent the values of the left, right, and parent pointer respectively
  76.  
  77. */
  78. template <class T>
  79. Node<T>::Node(T Tdata, Node *pL, Node* pR, Node *pParent, bool bColour)
  80. {
  81.     data = Tdata;
  82.     parent = pParent;
  83.     left = pL;
  84.     right = pR;
  85.     parent = pParent;
  86.     isBlack = bColour;
  87. }
  88. /*
  89.     C'tor that takes in four parameters
  90.     a datum, node pointers representing left and right child respectively and a colour value by a boolean
  91. */
  92. template <class T>
  93. Node<T>::Node(T Tdata, Node *pL, Node* pR, bool bColour)
  94. {
  95.     data = Tdata;
  96.     parent = NULL;
  97.     left = pL;
  98.     right = pR;
  99.     isBlack = bColour;
  100. }
  101.  
  102. /*
  103.     End of Node class constructors,
  104.  
  105.     Red Black tree constructor is below, initializing the root pointer to NULL
  106.     and other private attributes to defaults
  107.    
  108. */
  109. template <class T>
  110. RedBlackTree<T>::RedBlackTree()
  111. {
  112.     root = NULL;
  113.     aDumpData = NULL;
  114.     iNodePos = 0;
  115.     aDumpTemp = NULL;
  116.    
  117. }
  118. /*
  119.     RB Copy constructor which uses an internal helper function to make a deep copy of the tree
  120. */
  121. template <class T>
  122. RedBlackTree<T>::RedBlackTree(const RedBlackTree<T> &rhs)
  123. {
  124.     root = CloneTree(rhs.root);
  125. }
  126.  
  127. /*
  128.     Overloaded assignment operator which returns a pointer to a RB [Red Black] Tree object,
  129.         Logic:
  130.             1. Run alias test
  131.             2. Deallocate memory for calling object
  132.             3. Make deep copy of target
  133. */
  134. template <class T>
  135. RedBlackTree<T> & RedBlackTree<T>::operator=(const RedBlackTree<T> &rhs)
  136. {
  137.     if(this != &rhs)
  138.     {
  139.         // deallocate memory for the calling object
  140.        
  141.         removeAll();
  142.         // make a deep copy of its target
  143.         root = CloneTree(rhs.root);
  144.     }
  145.     return *this;
  146.  
  147. }
  148. /*
  149.     Destructor for RB tree,
  150.     uses a helper function to deallocate all nodes allocated on the heap to build the tree
  151. */
  152. template <class T>
  153. RedBlackTree<T>::~RedBlackTree()
  154. {
  155.     removeAll();
  156. }
  157.  
  158. /*
  159.     Internal private helper function that gets called by the public insert method
  160.         Takes in a pointer to a node as a parameter
  161.         Returns true if the insert is successful false if the client attempts to insert duplicate items into the tree
  162.         pointer x determines point of insertion
  163.         pointer y determines the node before x so we know where to wedge the node we want to insert
  164. */
  165. template <class T>
  166. bool RedBlackTree<T>::bInsert(Node<T>* pNode)
  167. {
  168.     Node<T> *y = NULL;
  169.     Node<T> *x = root;
  170.     bool bIns = false; // return value
  171.     bool bFound = false;
  172.    
  173.     // false to indicate that the value is not already in the tree, true to denote that the value is already there
  174.     if(bPrivSearch(pNode->data, root) == true)
  175.     {
  176.         bIns = false;
  177.         bFound = true;
  178.     }
  179.     if(bFound == false)
  180.     {
  181.         while(x != NULL)
  182.         {
  183.             y = x;
  184.             if(pNode->data < x->data)
  185.             {
  186.                 x = x->left;
  187.  
  188.             }
  189.             else
  190.             {
  191.                 x = x->right;
  192.            
  193.             }
  194.         }  // while loop
  195.         pNode->parent = y;
  196.         if(y == NULL)
  197.         {
  198.             root = pNode;
  199.         }
  200.         else if(pNode->data < y->data)
  201.         {
  202.             y->left = pNode;
  203.         }
  204.         else
  205.         {
  206.             y->right = pNode;
  207.         }
  208.         pNode->left = NULL;
  209.         pNode->right = NULL;
  210.         pNode->isBlack = false;
  211.         vInsertFixViolation(pNode);
  212.         bIns = true;
  213.     }
  214.              
  215.     return bIns;
  216. }
  217.  
  218.  
  219. /*
  220.     Helper function that allows us to fix any violations that we may have when inserting into the tree
  221.         Returns nothing since the function is void, takes in a node pointer as a parameter
  222.  
  223.         Violations that can occur when inserting a node into an RB tree
  224.             1.  the node's left uncle is red
  225.             2.  the node's uncle is black and the node is a right child
  226.             3.  the node's uncle is black and the node is a left child
  227.             =========================================================
  228.             Symmetric cases
  229.             =========================================================
  230.             4.  the node's right uncle is red
  231.             5.  the node's uncle is black and the node is a left child
  232.             6.  the node's uncle is black and the node is a right child
  233.         How to fix these issues, note case 1,2, and 3 and 4,5,6 are symmetrical counterparts
  234.             To fix case one we just perform colour changes by making the node's parent black and its uncle also black
  235.             To fix case two, we just simply make case 2 fall into case 3 since the two cases are not mutually exclusive
  236.                 To enter case 2 via 3 we immediately perform a left rotation about the node we have just inserted
  237.                 Afterwards we can fix case 3 by performing colour changes and a right rotation about that node's grandparent
  238.         Return type is void and the function does not return anything
  239.         Parameter is a node pointer which represents the node we would like to insert
  240.            
  241. */
  242. template <class T>
  243. void RedBlackTree<T>::vInsertFixViolation(Node<T> *pNode)
  244. {
  245.     Node<T> *y;
  246.     while((pNode != root)&&(pNode->parent->isBlack == false))// start of while
  247.     {
  248.         //start if
  249.         if((pNode->parent != NULL )&&(pNode->parent == pNode->parent->parent->left))
  250.         {
  251.             y = pNode->parent->parent->right; // the right uncle of y
  252.             if((y!=NULL)&&(y->isBlack == false))
  253.             {
  254.                 pNode->parent->isBlack = true;
  255.                 y->isBlack = true;
  256.                 pNode->parent->parent->isBlack = false;
  257.                 pNode = pNode->parent->parent;
  258.             }
  259.             else
  260.             {
  261.                 if(pNode == pNode->parent->right)
  262.                 {
  263.                     pNode = pNode->parent;
  264.                     LeftRotation(pNode);
  265.                 }
  266.                 if(pNode->parent != NULL)
  267.                 {
  268.                     pNode->parent->isBlack = true;
  269.                     if(pNode->parent->parent != NULL)
  270.                     {
  271.                         pNode->parent->parent->isBlack = false;//
  272.                         RightRotation(pNode->parent->parent);
  273.                     }
  274.                    
  275.                 }
  276.                
  277.             }
  278.         }// end if
  279.         else
  280.         {//
  281.         /*start of else*/
  282.             if(pNode->parent == pNode->parent->parent->right)
  283.             {
  284.                 y = pNode->parent->parent->left; // uncle of node pNode on the left side;
  285.                 if((y!= NULL)&&(y->isBlack == false))
  286.                 {
  287.                     pNode->parent->isBlack = true;
  288.                     y->isBlack = true;
  289.                     pNode->parent->parent->isBlack = false;
  290.                     pNode = pNode->parent->parent;
  291.                 }
  292.                 else
  293.                 {
  294.                     if(pNode == pNode->parent->left)
  295.                     {
  296.                         pNode = pNode->parent;
  297.                         RightRotation(pNode);
  298.                     }
  299.                     if(pNode->parent != NULL)
  300.                     {
  301.                         pNode->parent->isBlack = true;
  302.                         if(pNode->parent->parent != NULL)
  303.                         {
  304.                             pNode->parent->parent->isBlack = false;
  305.                             LeftRotation(pNode->parent->parent);
  306.                         }
  307.                     }
  308.                
  309.                 }
  310.             }              
  311.         }// end of else
  312.     }// end of while
  313.     root->isBlack = true;
  314. }
  315. /*
  316.     A private helper function that will enable us to return a pointer to a node in a tree,
  317.     if it doesn't exist we just simply return NULL
  318.     else we keep searching the right or left subtrees as needed until we reach the appropriate spot in the
  319.     tree in which its node contains the appropriate datum that we are trying to find.
  320.     Takes in two parameters: the data we would like to search for and a node pointer indicating where we would
  321.     like to start the recursion
  322.     Return: a pointer to the node indicating where in the tree our data is contained in, if it doesn't exist it simply returns NULL
  323. */
  324. template <class T>
  325. Node<T>* RedBlackTree<T>::pSearchPriv(T dataS, Node<T> *pTr)
  326. {
  327.     if(pTr == NULL)
  328.     {
  329.         return NULL;
  330.     }
  331.     else if(dataS < pTr->data)
  332.     {
  333.         return pSearchPriv(dataS,pTr->left);
  334.     }
  335.     else if(pTr->data < dataS)
  336.     {
  337.         return pSearchPriv(dataS,pTr->right);
  338.     }
  339.     else
  340.     {
  341.         return pTr;
  342.     }
  343.  
  344. }
  345.  
  346. /*
  347.     Public search function:
  348.     Takes in the data we would like to find as a parameter
  349.     Returns true or false depending if we find that specific data or not.
  350. */
  351. template <class T>
  352. bool RedBlackTree<T>::search(T data) const
  353. {
  354.     return bPrivSearch(data,root);
  355. }
  356. /*
  357.     Follows the same structure as the other privateSearch function
  358.     but returns a boolean instead
  359.     takes in a datum to search for and a node pointer to start the recursion as parameters
  360. */
  361. template <class T>
  362. bool RedBlackTree<T>::bPrivSearch(T dataS, Node<T> *pTr) const
  363. {//
  364.     if((pTr == NULL))
  365.     {
  366.         return false;
  367.     }
  368.     else if(dataS < pTr->data)
  369.     {
  370.         return bPrivSearch(dataS,pTr->left);
  371.     }
  372.     else if(pTr->data < dataS)
  373.     {
  374.         return bPrivSearch(dataS, pTr->right);
  375.     }
  376.     else
  377.     {
  378.         return true;
  379.     }
  380. }
  381. /*
  382.     Void helper function that enables us to perform a left rotation
  383.     takes in a Node pointer which indicates the node we are rotating about
  384.     while maintaining the BST properties
  385.  
  386.     Return is none since the function is void
  387. */
  388. template <class T>
  389. void RedBlackTree<T>:: LeftRotation(Node<T> *pNode)
  390. {
  391.     Node<T> *y = pNode->right; // y is pNode's right child
  392.     pNode->right = y->left; // make y's left subtree  into Pnode's right
  393.    
  394.     if(y->left != NULL)
  395.     {
  396.         y->left->parent = pNode;
  397.     }
  398.     y->parent = pNode->parent; // link the parent of y to pNode's
  399.     if(pNode->parent == NULL) // special case if we are rotating about the root
  400.     {
  401.         root = y;
  402.     }
  403.     else
  404.     {
  405.         if(pNode == pNode->parent->left) // checking if pNode is a left or right child
  406.         {
  407.             pNode->parent->left = y;
  408.         }
  409.         else
  410.         {
  411.             pNode->parent->right = y;
  412.         }
  413.     }
  414.  
  415.     y->left = pNode; // reposition subtrees
  416.     pNode->parent = y;
  417. }
  418. /*
  419.     Private helper function that enables right rotations
  420.     takes in a node pointer that indicates the node we perform the
  421.     rotation about,
  422.  
  423.     Return type is void so function does not return anything
  424. */
  425. template <class T>
  426. void RedBlackTree<T>::RightRotation(Node<T> *pNode)
  427. {
  428.     Node<T> *y = pNode->left; // y is pNode's left child
  429.     pNode->left = y->right; // make pNode's left subtree become y's right
  430.     if(y->right != NULL)
  431.     {
  432.         y->right->parent = pNode;
  433.     }
  434.     y->parent = pNode->parent;
  435.     if(pNode->parent == NULL) // special case if pNode is the root
  436.     {
  437.         root = y;
  438.     }
  439.     else
  440.     {
  441.         if(pNode == pNode->parent->right) // checking if the node we want to rotate about is a right or left child
  442.         {
  443.             pNode->parent->right = y;
  444.         }
  445.         else
  446.         {
  447.             pNode->parent->left = y;
  448.         }
  449.     }
  450.     /* repositioning subtrees */
  451.     y->right = pNode;
  452.     pNode->parent = y;
  453. }
  454.  
  455. /*
  456.     Private helper function that enables us to print the whole tree
  457.     takes in a pointer to a node to indicate the start of the recursion
  458.     return type is none since it is void
  459. */
  460. template <class T>
  461. void RedBlackTree<T>::PrintRecurse(Node<T> *pTr)
  462. {
  463.     int i = 0;
  464.     if(pTr != NULL)
  465.     {
  466.         //i++;
  467.         PrintRecurse(pTr->left);
  468.         std::cout << pTr->data << "";
  469.         //i++;
  470.         std::cout << "[" ;
  471.         if(pTr->isBlack == true)
  472.         {
  473.             std::cout << "Black" << " ";
  474.         }
  475.         else
  476.         {
  477.             std::cout << "Red" << " ";
  478.         }
  479.         std::cout << "]";
  480.         if(pTr->parent != NULL)
  481.         {
  482.             std::cout<< "(" << "parent is " << pTr->parent->data << ")" <<endl;
  483.         }
  484.         else
  485.         {
  486.             std::cout << endl;
  487.         }
  488.         PrintRecurse(pTr->right);
  489.         //i++;
  490.        
  491.     }
  492.     return;
  493. }
  494. /*
  495.     Public print function that takes in no parameters and calls a private
  496.     helper print function which starts its recursion from the root
  497. */
  498. template <class T>
  499. void RedBlackTree<T>::Print()
  500. {
  501.     PrintRecurse(root);
  502. }
  503. /*
  504.     Public insert function which takes a data that one wants to insert
  505.     and calls a private helper function which takes a node allocated in dynamic memory as a parameter
  506.     Returns a boolean
  507. */
  508. template <class T>
  509. bool RedBlackTree<T>::insert(T datum)
  510. {
  511.     Node<T> *pNewNode = new Node<T>(datum);
  512.     pNewNode->isBlack = true;
  513.     pNewNode->parent = NULL;
  514.     pNewNode->left = NULL;
  515.     pNewNode->right = NULL;
  516.     return bInsert(pNewNode);
  517. }
  518.  
  519. /* 
  520.     Helper function that allows us to find the successor node in the Red-Black tree
  521.     takes in a pointer to a node as a parameter to indicate the start of the recursion
  522.     returns the minimum value in the subtree it was starting the recursion from
  523. */
  524. template <class T>
  525. Node<T>* RedBlackTree<T>::findMinPriv(Node<T> *pNode)
  526. {
  527.     if(pNode == NULL)
  528.     {
  529.         return NULL;
  530.     }
  531.     if(pNode->left == NULL)
  532.     {
  533.         return pNode;
  534.     }
  535.     return findMinPriv(pNode->left);
  536. }
  537. /*
  538.     Public function for debugging purposes,
  539.     calls a private helper function so we can recursively
  540.     search the left subtree for the appropriate node
  541. */
  542. template <class T>
  543. T RedBlackTree<T>::findMin()
  544. {
  545.     Node<T> *pTr = findMinPriv(root);
  546.    
  547.     T iMin;
  548.     if(pTr != NULL)// check if the pointer is NULL first since the tree can be empty
  549.     {
  550.         iMin = pTr->data;
  551.     }
  552.     return iMin;
  553. }
  554. /*
  555.     Public function that takes in a datum that we would like to remove as a parameter
  556.     returns false if the removal was unsuccessful or the datum is already there
  557.     returns true  if the removal was successful or the datum wasn't inserted previously
  558.         calls a private helper function that does the removal
  559. */
  560. template <class T>
  561. bool RedBlackTree<T>::remove(T data)
  562. {
  563.     bool bRmv = false;
  564.     Node<T>* pNodetoRemove = pSearchPriv(data,root);
  565.     if(pNodetoRemove!= NULL)
  566.         bRmv = bRemove(pNodetoRemove);
  567.     else
  568.     {
  569.         bRmv = false;
  570.     }
  571.     return bRmv;
  572. }
  573. /*
  574.     Private helper function that enables us to reassign pointers as needed to remove the node
  575.     while preserving the BST tree properties
  576. */
  577. template <class T>
  578. bool RedBlackTree<T>::bRemove(Node<T> *pNode)
  579. {
  580.     Node<T> *y;
  581.     Node<T> *x;
  582.     bool bYOrigColour = false;
  583.     bool bFound = false;// boolean flag indicating to us if the node is found or not
  584.     bool bDel = false; // return value
  585.     /* Checks if the node we would like to remove exists*/
  586.     if ((pNode != NULL)&&(bPrivSearch(pNode->data,root) == true))
  587.     {
  588.         bDel = false;
  589.         bFound = true;
  590.     }
  591.  
  592.  
  593.     // Case 1: node has no children = remove
  594.     // Case 2: node has 1 children = move right or left, ignore node
  595.     // Case 3: node has 2 children = find the successor and swap contents
  596.     // case that z has one or no children else z has two children
  597.  
  598.     y = ((pNode->left == NULL)) || ((pNode->right == NULL)) ?
  599.     pNode:
  600.     findMinPriv(pNode->right);
  601.     // the node we want to remove
  602.  
  603.     x =  (y->left != NULL)?
  604.     y->left:
  605.     y->right;
  606.     // indicates point of insertion
  607.    
  608.     if(x != NULL)
  609.     {
  610.         x->parent = y->parent;
  611.     }
  612.     if(y->parent == NULL)
  613.     {
  614.         root = x;
  615.     }
  616.     else
  617.     {
  618.         if( y == y->parent->left)
  619.         {
  620.             y->parent->left = x;
  621.         }
  622.         else
  623.         {
  624.             y->parent->right = x;
  625.         }
  626.  
  627.     }
  628.     if( y!= pNode)
  629.     {
  630.         pNode->data = y->data;
  631.     }
  632.     if( (x!= NULL)&& (y->isBlack == true))
  633.     {
  634.         vPrivDeleteFix(x);
  635.     }
  636.     delete y;
  637.     y = NULL;
  638.     bDel = true;
  639.     return bDel;
  640. }
  641.  
  642. /*
  643.     Helper function that allows us to fix RB tree violations when deleting a node from a tree
  644.     Eight cases to consider, the latter three are symmetrical:
  645.     1. The child of the node we want to remove [x] has a red sibling
  646.     2. The child of the node we want to remove has a sibling that is black and both of that sibling's children are black
  647.     3. The child of the node we want to remove has a sibling that is black, the sibling's left child is red, and the sibling's right child is black
  648.     4. The child of the node we want to remove has a black sibling and that sibling's right child is red.
  649.     ================================================================================================================================================
  650.  
  651.     Symmetric cases:
  652.         5. The child of the node we want to remove [x] has a red sibling
  653.         6. The child of the node we want to remove has a sibling that is black and both of that sibling's children are black
  654.         7. The child of the node we want to remove has a sibling that is black, the sibling's right child is red, and the sibling's left child is black
  655.         8. The child of the node we want to remove has a black sibling and that sibling's left child is red.
  656.     How to deal with case 1/[5]:
  657.         Switch the colours of the sibling and x's parent then perform a left rotation about x's parent
  658.         Case 1 can then be converted to case 2,3,4 or 6,7,8 depending on the shape of the tree
  659.     How to deal with case 2/[6]:
  660.         Both of the sibling's children are black. In addition that sibling node is also black so one can take a
  661.         black off both the child of the node we want to remove. To compensate we add an extra black to the x's parent
  662.     How to deal with case 3/[7]:
  663.         We swap the colours of x's sibling and its left [right] child and then perform a right [left] rotation
  664.     How to deal with case 4/[8]:
  665.         Perform colour changes and a left [right] rotation
  666.     Return type is none since the function is of type void parameter is a node pointer which represents
  667.     the child of the node we want to remove
  668.  
  669. */
  670. template <class T>
  671. void RedBlackTree<T>::vPrivDeleteFix(Node<T> *pNode)
  672. {
  673.     //Node *rootChild = root->left;
  674.     Node<T> *w; // pointer to allow us to find pNode's sibling which will take y's place in the tree
  675.     while((pNode!= NULL)&&(pNode != root) && (pNode->isBlack == true))
  676.     {
  677.         if(pNode == pNode->parent->left)
  678.         {
  679.             w = pNode->parent->right;
  680.             if((w!= NULL)&&(w->isBlack == false))// case 1
  681.             {
  682.                 w->isBlack = true;
  683.                 pNode->parent->isBlack = false;
  684.                 LeftRotation(pNode->parent);
  685.                 w = pNode->parent->right;
  686.             }
  687.             if((w != NULL)&& (w->left!=NULL) && (w->right!=NULL)
  688.                 && (w->left->isBlack == true) && (w->right->isBlack == true))
  689.             {
  690.                 w->isBlack = false;
  691.                 pNode = pNode->parent;
  692.             }
  693.             else
  694.             {
  695.                 if((w != NULL) && (w->left!=NULL) && (w->right!=NULL)
  696.                     &&(w->right->isBlack == true))
  697.                 {
  698.                     w->left->isBlack = true;
  699.                     w->isBlack = false;
  700.                     RightRotation(w);
  701.                     w = pNode->parent->right;
  702.                 }
  703.                 if((w!= NULL) && (pNode->parent != NULL))
  704.                 {
  705.                     w->isBlack = pNode->parent->isBlack;
  706.                 }
  707.                 if(pNode->parent != NULL)
  708.                 {
  709.                     pNode->parent->isBlack = true;
  710.                 }
  711.                 if( (w != NULL) && (w->right != NULL))
  712.                 {
  713.                     w->right->isBlack = true;
  714.                 }
  715.                 if(pNode->parent != NULL)
  716.                 {
  717.                     LeftRotation(pNode->parent);
  718.                 }
  719.                 pNode = root;
  720.             }
  721.         }
  722.         else
  723.         {
  724.             if(pNode == pNode->parent->right)
  725.             {
  726.                 w = pNode->parent->left;
  727.                 if( (w!= NULL) && (w->isBlack == false))
  728.                 {
  729.                     w->isBlack = true;
  730.                     pNode->parent->isBlack = false;
  731.                     if(pNode->parent != NULL)
  732.                     {
  733.                         RightRotation(pNode->parent);
  734.                         w = pNode->parent->left;
  735.                     }
  736.                    
  737.                 }
  738.                 if( (w != NULL) && (w->left!=NULL) && (w->right!=NULL)
  739.                     && (w->right->isBlack == true) && (w->left->isBlack == true))
  740.                 {
  741.                     w->isBlack = false;
  742.                     pNode = pNode->parent;
  743.                 }
  744.                 else
  745.                 {
  746.                     if((w != NULL) && (w->left != NULL) && (w->right!=NULL)
  747.                         &&(w->left->isBlack == true))
  748.                     {
  749.                         w->right->isBlack = true;
  750.                         w->isBlack = false;
  751.                         LeftRotation(w);
  752.                         w = pNode->left;
  753.                     }
  754.                     if((w!= NULL) && (pNode->parent != NULL))
  755.                     {
  756.                         w->isBlack = pNode->parent->isBlack;
  757.                     }
  758.                     if(pNode->parent != NULL)
  759.                     {
  760.                         pNode->parent->isBlack = true;
  761.                     }
  762.                     if( (w != NULL) && (w->left != NULL))
  763.                     {
  764.                         w->left->isBlack = true;
  765.                     }
  766.                     if(pNode->parent != NULL)
  767.                     {
  768.                         RightRotation(pNode->parent);
  769.                     }
  770.                     pNode = root; // to exit while loop
  771.                 }
  772.             }
  773.         }
  774.     }
  775.     if(pNode != NULL)
  776.     {
  777.         pNode->isBlack = true;
  778.     }
  779.      
  780. }
  781.  
  782. /*
  783.     A private helper function that enables us to find the height of a binary search tree
  784.     The function takes in a Node pointer which indicates the start of the recursion, the
  785.     return type is an integer representing the height
  786.     Logic is as follows:
  787.         1. if the node is Null then the tree has height zero.
  788.         2. else we employ the recursive definition of height to perform our desired calculation
  789.  
  790. */
  791. template <class T>
  792. int RedBlackTree<T>:: heightHelper(Node<T> *pNode) const
  793. {
  794.     int iHeight = 0;
  795.     if(pNode == NULL)
  796.     {
  797.         iHeight = 0;
  798.     }
  799.     else
  800.     {
  801.         iHeight = 1+ max(heightHelper(pNode->right),heightHelper(pNode->left));
  802.     }
  803.     return iHeight;
  804. }
  805. /*
  806.     Private helper that enables us to find the amount of nodes in a binary search tree
  807.     Takes in a Node pointer as a parameter which indicates the start of the recursion
  808.     the return type is the amount of nodes in both of the subtrees including the root
  809. */
  810. template <class T>
  811. int RedBlackTree<T>::sizeHelper(Node<T> *pNode) const
  812. {
  813.     if(pNode == NULL)
  814.     {
  815.         return 0;
  816.     }
  817.     else
  818.     {
  819.         return (sizeHelper(pNode->left)+ sizeHelper(pNode->right))+1;
  820.     }
  821. }
  822. /*
  823.     Public function that enables us to find the height of a tree
  824.     no parameters are taken and the return type is an integer value denoting
  825.     the amount of nodes in the tree
  826. */
  827. template <class T>
  828. int RedBlackTree<T>::height() const
  829. {
  830.     return heightHelper(root);
  831. }
  832. /*
  833.     Public function that allows us to find the amount of nodes in the tree
  834.     no parameters are taken and the return type is an integer value denoting the amount of
  835.     nodes in the tree
  836. */
  837. template <class T>
  838. int RedBlackTree<T>::size() const
  839. {
  840.      return sizeHelper(root);
  841. }
  842. /*
  843.     Internal private function that takes in an node pointer in which to start the recursion so we clear all
  844.     of the nodes in the binary search tree or any tree that contains two children, note we employ a post order traversal because
  845.     we want to clear both the right and left subtrees before visiting the node. In addition, we set our node to NULL for good practice
  846. */
  847. template <class T>
  848. void RedBlackTree<T>:: DeleteTreePrivate(Node<T>* pNode)
  849. {
  850.     if(pNode != NULL)
  851.     {
  852.         DeleteTreePrivate(pNode->left);
  853.         DeleteTreePrivate(pNode->right);
  854.         delete pNode;
  855.     }
  856.     pNode = NULL;
  857. }
  858. /*
  859.     Public remove function that allows us to deallocate all of the nodes in the binary search tree
  860.     takes in no parameters and doesn't return anything
  861.     Calls a private helper function that deletes all of the nodes of the tree with the recursion starting at the root
  862. */
  863. template <class T>
  864. void RedBlackTree<T>::removeAll()
  865. {
  866.     if (root)
  867.     {
  868.         DeleteTreePrivate(root);
  869.         root = NULL;
  870.     }
  871. }
  872. /*
  873.     Private helper function that enables us to deep copy the binary search tree
  874. */
  875. template <class T>
  876. Node<T> *RedBlackTree<T>::CloneTree(const Node<T>* pTr)
  877. {
  878.     Node<T> *pNewRB = NULL;
  879.     if(pTr != NULL)
  880.     {
  881.         //pNewRB = new Node<T>(pTr->data,NULL,NULL, NULL,pTr->isBlack); >> this piece was used for debugging purposes
  882.         pNewRB = new Node<T>(pTr->data,pTr->left,pTr->right, pTr->parent,pTr->isBlack);
  883.         pNewRB->left = CloneTree(pTr->left);
  884.         pNewRB->right = CloneTree(pTr->right);
  885.     }
  886.     return pNewRB;
  887. }
  888. /*
  889.     This function takes in no parameters and returns the root as a NODE POINTER!
  890. */
  891. template <class T>
  892. Node<T>* RedBlackTree<T>:: getRoot()
  893. {
  894.     return root;
  895. }
  896. /*
  897.     The dump function takes in an integer reference parameter that returns the total amount of items in the array
  898.     The function returns an array in dynamic memory
  899. */
  900. template <class T>
  901. T* RedBlackTree<T>::dump(int& iSize)
  902. {
  903.     //int iStart = 0;
  904.     iSize = size();
  905.     int iPosi = 0;
  906.     iNodePos = 0;
  907.  
  908.     if(iSize > 0)
  909.     {
  910.         aDumpData = new T[iSize];
  911.         dumpPrivate(root,iPosi);
  912.     }
  913.     return aDumpData;
  914.  
  915. }
  916. /*
  917.     This helper function takes in two parameters, a pointer to a node in which to start the recursion
  918.     and an integer reference parameter to check if we incremented our index correctly 'i.e iNodePos
  919. */
  920. template <class T>
  921. void RedBlackTree<T>::dumpPrivate(Node<T> *pNode,int &iPos)
  922. {
  923.     if(pNode != NULL)
  924.     {
  925.         dumpPrivate(pNode->left,iPos);
  926.         aDumpData[iNodePos] = pNode->data;
  927.         iNodePos++;
  928.         dumpPrivate(pNode->right,iPos);
  929.     }
  930.    
  931. }
  932. /*
  933.     Ok we must admit, we are making a risky assumption that our first parameter is less than our second parameter however in practice
  934.     we are probably going to have to switch that around.
  935.     The function takes the following parameters:
  936.         two values that represent the range that the user is looking for
  937.         an integer reference parameter that denotes the amount of items in the returned array
  938.     Returns a pointer to an array in dynamic memory
  939.     If there are no values between the first and second parameters the function returns NULL
  940.     i.e search(15,19,n) returns NULL if the array looks like this
  941.     [1,5,11,13,14,21,25,30,63]
  942.     If the first parameter equals second parameter and that particular value is in the tree then the function should return that value
  943.     i.e search(0,0,n) should return 0 if the array looks like this
  944.     [0.33.99]
  945.     but returns NULL if the array looks like this
  946.     [33,99]
  947.     If the tree is empty it should return NULL
  948. */
  949.  
  950. template <class T>
  951. T *RedBlackTree<T>::search(T firstParem, T secondParem, int &iNumElements)
  952. {
  953.     iNumElements = size();
  954.     int iLocIndex = 0;
  955.     T *aDumpBetweenValues = NULL;
  956.     iNodePos = 0;
  957.     firstvalue = firstParem;
  958.     secondvalue = secondParem;
  959.     if(iNumElements > 0) // checks if the tree is empty
  960.     {
  961.         aDumpTemp = new T[iNumElements]; // allocates enough memory for all of the nodes in the tree
  962.         searchPrivate(root,iLocIndex);// helper function to search the tree for the datums in the requested bounds
  963.         if(iLocIndex > 0)// checks if there are any values in between the two parameters
  964.         {
  965.             aDumpBetweenValues = new T[iLocIndex]; // allocates enough memory for all of the values that are between parameter 1 and parameter 2
  966.             // we use a local memory allocation so we don't have to worry about that memory block used by a previous search call
  967.            
  968.  
  969.             // copies the values yielded from searchPrivate over to the memory allocated just enough for all of the values in
  970.             // between the bounds
  971.             for(int i = 0;i<iLocIndex;i++)
  972.             {
  973.                 aDumpBetweenValues[i] = aDumpTemp[i];
  974.             }
  975.             // we set our iNumElements integer parameter to the amount of values that are in between our bounds
  976.             iNumElements = iLocIndex;
  977.         }
  978.         else
  979.         {
  980.             iNumElements = 0;
  981.         }
  982.         if(aDumpTemp!= NULL)
  983.         {
  984.             delete [] aDumpTemp;
  985.             aDumpTemp = NULL;
  986.         }
  987.  
  988.     }
  989.     else
  990.     {
  991.         iNumElements = 0;
  992.     }
  993.     return aDumpBetweenValues;
  994.    
  995. }
  996. /*
  997.     Helper function that will allow us to search the left and right subtrees
  998.         Parameters are a pointer to a node that will enable us to start the recursion and an integer reference parameter
  999.         to keep track the amount of items inserted into the array
  1000. */
  1001. template <class T>
  1002. void RedBlackTree<T>::searchPrivate(Node<T>*pTr1, int &iNdex)
  1003. {
  1004.     // base case
  1005.     if(pTr1 == NULL)
  1006.     {
  1007.         return;
  1008.     }
  1009.     /*If the current value we are looking at is greater than the first value in the range
  1010.         that we are looking for we keep on traversing the left subtree
  1011.     */
  1012.     if(firstvalue < pTr1->data)
  1013.     {
  1014.         searchPrivate(pTr1->left,iNdex);   
  1015.     }
  1016.     /*
  1017.         If the value we are looking for is indeed in the range we push its appropriate datum into the associated
  1018.         index in the array.
  1019.     */
  1020.     if( firstvalue <= pTr1->data && secondvalue >= pTr1->data)
  1021.     {
  1022.         aDumpTemp[iNdex] = pTr1->data;
  1023.         iNdex++;
  1024.     }
  1025.  
  1026.     /*
  1027.         If the current node with its associated datum is less than the datum in the second value of our interval
  1028.         then we keep on recursively going down its right subtree
  1029.     */
  1030.     if(secondvalue > pTr1->data)
  1031.     {
  1032.         searchPrivate(pTr1->right,iNdex);
  1033.     }
  1034. }
  1035. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement