Phr0zen_Penguin

BinarySearchTree.h - VTC C++ Binary Search Tree

May 19th, 2015
487
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 17.39 KB | None | 0 0
  1. /**
  2.  * [BinarySearchTree.h]
  3.  * The BinarySearchTree class declaration/specification.
  4.  */
  5.  
  6. #ifndef BINARYSEARCHTREE_H
  7. #define BINARYSEARCHTREE_H
  8.  
  9. #include "LinkedQueue.h"
  10. #include <iostream>
  11.  
  12. /**
  13.  * OrderType ENUM:
  14.  * Used to specify the order in which the tree must be traversed:
  15.  *
  16.  * Pre-order traversal:
  17.  * The node itself is visited first, then all the nodes in the left sub-tree, then all the nodes in
  18.  * the right sub-tree.
  19.  *
  20.  * In-order traversal:
  21.  * All the nodes in the left sub-tree are visited first, then the node itself, then all the nodes in
  22.  * the right sub-tree.
  23.  *
  24.  * Post-order traversal:
  25.  * All the nodes in the left sub-tree are visited first, then all the nodes in the right sub-tree,
  26.  * then the node itself.
  27.  */
  28. enum OrderType { PRE_ORDER, IN_ORDER, POST_ORDER };
  29.  
  30. /**
  31.  * TreeNode STRUCTURE:
  32.  * Used to created nodes for the tree.
  33.  */
  34. template <class ItemType>
  35. struct TreeNode
  36. {
  37.     ItemType    element;
  38.     TreeNode    *left;
  39.     TreeNode    *right;
  40. };
  41.  
  42.  
  43. template <class ItemType>
  44. class BinarySearchTree
  45. {
  46.     /**
  47.      * Everything under public can be accessed by all other programs or classes.
  48.      */
  49.     public:
  50.         /**
  51.          * Constructor(s):
  52.          */
  53.         BinarySearchTree();
  54.  
  55.         /**
  56.          * Destructor:
  57.          */
  58.         ~BinarySearchTree();
  59.  
  60.         /**
  61.          * Mutators:
  62.          */
  63.         void InsertItem(ItemType);
  64.         void DeleteItem(ItemType);
  65.  
  66.         /**
  67.          * Accessors:
  68.          */
  69.         void RetrieveItem(ItemType &, bool &);
  70.         void GetNextItem(ItemType &, OrderType, bool &);
  71.  
  72.         /**
  73.          * General Use:
  74.          */
  75.         void MakeEmpty(void);
  76.         bool IsEmpty(void);
  77.         bool IsFull(void);
  78.         int NumberOfNodes(void);
  79.         void ResetTree(OrderType order);
  80.         void PrintTree(void);
  81.  
  82.  
  83.     /**
  84.      * Everything under protected can be accessed only by the class itself or (derived) subclasses,
  85.      * as in the case of inheritance.
  86.      */
  87.     protected:
  88.  
  89.  
  90.     /**
  91.      * (Private) DATA MEMBERS/PROPERTIES:
  92.      *
  93.      * Everything under private can only be accessed by the class itself (the code in the
  94.      * implementation file).
  95.      */
  96.     private:
  97.         TreeNode<ItemType>      *root;
  98.         LinkedQueue<ItemType>   preQueue;
  99.         LinkedQueue<ItemType>   postQueue;
  100.         LinkedQueue<ItemType>   inQueue;
  101. };
  102.  
  103. #endif // BINARYSEARCHTREE_H
  104.  
  105.  
  106. /**
  107.  * The BinarySearchTree class definition/implementation.
  108.  */
  109.  
  110. /**
  111.  * BinarySearchTree CLASS CONSTRUCTOR(s):
  112.  */
  113. template <class ItemType>
  114. BinarySearchTree<ItemType>::BinarySearchTree()
  115. {
  116.     root = 0;   // nullifies the root of the tree
  117. }
  118.  
  119.  
  120. /**
  121.  * BinarySearchTree CLASS MUTATORS:
  122.  */
  123. template <class ItemType>
  124. void BinarySearchTree<ItemType>::InsertItem(ItemType item)
  125. {
  126.     /**
  127.      * To insert an item into the tree, code will be implemented to do a recursive search, starting
  128.      * at its root, and check if the item is bigger or smaller than each item therein.
  129.      *
  130.      * While the item is still smaller, the search will continue to the left, until the condition is
  131.      * false (a null value is found), then the item will be inserted.
  132.      */
  133.     Insert(root, item);
  134. }
  135.  
  136. template <class ItemType>
  137. void BinarySearchTree<ItemType>::DeleteItem(ItemType item)
  138. {
  139.     /**
  140.      * To delete an item from the tree, code will be implemented to do a recursive search, starting
  141.      * at its root, and check if the item is bigger or smaller than each item therein.
  142.      *
  143.      * While the item is still smaller, the search will continue on the left, until the condition is
  144.      * is met (either the items are equal or the item is not found (the item is not longer smaller
  145.      * or a null value is reached)).
  146.      *
  147.      * The same technique will be used to search on the right side of the tree if the item is larger.
  148.      *
  149.      * If the item is found, the tree will be passed to an auxiliary function that will perform the
  150.      * deletion (of the node containing the found item).
  151.      */
  152.     Delete(root, item);
  153. }
  154.  
  155.  
  156. /**
  157.  * BinarySearchTree CLASS ACCESSORS:
  158.  */
  159. template <class ItemType>
  160. void BinarySearchTree<ItemType>::RetrieveItem(ItemType &item, bool &found)
  161. {
  162.     /**
  163.      * To retrieve an item from the tree, code will be implemented to do a recursive search, starting
  164.      * at it its root, and check if the item either exists, is bigger or smaller than each item in
  165.      * the tree, or, in the case where only one item exists in the tree, if it is equal to the item
  166.      * being searched for.
  167.      *
  168.      * While the item is still smaller, the search will continue to the left, until the condition is
  169.      * if it is found.  In such a case, the founded item and the true boolean variable will be
  170.      * returned.  Otherwise, false will be returned.
  171.      */
  172.     Retrieve(root, item, found);
  173. }
  174.  
  175. template <class ItemType>
  176. void BinarySearchTree<ItemType>::GetNextItem(ItemType &item, OrderType order, bool &done)
  177. {
  178.     done = false;   // logical
  179.  
  180.         switch(order)
  181.         {
  182.             case PRE_ORDER:     // if the item must be retrieved using the pre-order method...
  183.                 preQueue.Dequeue(item); // ...get the item from the pre-queue
  184.  
  185.                     if(preQueue.IsEmpty()) done = true;     // if the pre-queue is empty (the item is not found), set 'done' to true as an indication
  186.                 break;
  187.  
  188.             case IN_ORDER:      // if the item must be retrieved using the in-order method...
  189.                 inQueue.Dequeue(item);  // ...get the item from the in-queue
  190.  
  191.                     if(inQueue.IsEmpty()) done = true;      // if the in-queue is empty (the item is not found), set 'done' to true as an indication
  192.                 break;
  193.  
  194.             case POST_ORDER:    // if the item must be retrieved using the post-order method...
  195.                 postQueue.Dequeue(item);    // ...get the item from the post-queue
  196.  
  197.                     if(postQueue.IsEmpty()) done = true;    // if the post-queue is empty (the item is not found), set 'done' to true as an indication
  198.                 break;
  199.  
  200.             default:
  201.                 break;
  202.         }
  203. }
  204.  
  205.  
  206. /**
  207.  * BinarySearchTree CLASS GENERAL USE FUNCTIONS:
  208.  */
  209. template <class ItemType>
  210. void BinarySearchTree<ItemType>::MakeEmpty(void)
  211. {
  212.     Destroy(root);      // the tree is simply destroyed.  Make careful note that this implementation, per se, is in no way identical to the destruction of the object itself.
  213. }
  214.  
  215. template <class ItemType>
  216. bool BinarySearchTree<ItemType>::IsEmpty(void)
  217. {
  218.     return (root == 0); // if the root is null, then the tree is empty... (DUH!  Such are the laws of nature my friend.)
  219. }
  220.  
  221. template <class ItemType>
  222. bool BinarySearchTree<ItemType>::IsFull(void)
  223. {
  224.     TreeNode<ItemType>  *pTemp = new TreeNode<ItemType>();  // attempt to allocate some memory for a new tree node
  225.  
  226.         if(pTemp == 0)  // if the previous attempted memory allocation failed a.k.a. if the temporary pointer is null...
  227.         {
  228.             return true;    // ...true is returned, indicating, more or less, a full tree
  229.         }
  230.         else            // ...
  231.         {
  232.             delete pTemp;   // ...free up the allocated memory location
  233.  
  234.             return false;   // ...return false, indicating a 'not-full' tree
  235.         }
  236. }
  237.  
  238. template <class ItemType>
  239. int BinarySearchTree<ItemType>::NumberOfNodes(void)
  240. {
  241.     /**
  242.      * NOTE:
  243.      * To count the number of nodes in the tree, code can be implemented to add the root node, plus
  244.      * the count of nodes on the left, plus the count of nodes on the right together. (1 + nL + nR)
  245.      *
  246.      * In order to achieve this, the tree will be recursed, and each sub-node will be added as 1 until
  247.      * no sub-node is left (a leaf is reached).
  248.      */
  249.  
  250.     return CountNodes(root);    // returns the result returned by the CountNodes() auxiliary function (which recursively counts the number of nodes in the tree)
  251. }
  252.  
  253. template <class ItemType>
  254. void BinarySearchTree<ItemType>::ResetTree(OrderType order)
  255. {
  256.     /**
  257.      * Check the tree traverse order type and call the relative function:
  258.      */
  259.     switch(order)
  260.     {
  261.         case PRE_ORDER:
  262.             PreOrder(root, preQueue);
  263.             break;
  264.         case IN_ORDER:
  265.             InOrder(root, inQueue);
  266.             break;
  267.         case POST_ORDER:
  268.             PostOrder(root, postQueue);
  269.             break;
  270.         default:
  271.             break;
  272.     }
  273. }
  274.  
  275. template <class ItemType>
  276. void BinarySearchTree<ItemType>::PrintTree(void)
  277. {
  278.     Print(root);
  279. }
  280.  
  281.  
  282. /**
  283.  * BinarySearchTree CLASS DESTRUCTOR(s):
  284.  */
  285. template <class ItemType>
  286. BinarySearchTree<ItemType>::~BinarySearchTree()
  287. {
  288.     /**
  289.      * NOTE:
  290.      * The implementation of the destructor will exploit the idea that the structure of the tree is
  291.      * recursive, so in order to destroy the tree, the action can start from the root, move to the
  292.      * left side, take the left side's first item as a root, then process the sub-tree, take another
  293.      * sub-tree until the leaf is reached, then finally destroy the leaf.
  294.      */
  295.  
  296.     /**
  297.      * Auxiliary Function (to destroy tree root):
  298.      */
  299.     Destroy(root);
  300. }
  301.  
  302.  
  303. /**
  304.  * AUXILIARY FUNCTION IMPLEMENTATIONS:
  305.  */
  306.  
  307. /**
  308.  * Destroy() AUXILIARY FUNCTION:
  309.  */
  310. template <class ItemType>
  311. void Destroy(TreeNode<ItemType> *&tree)
  312. {
  313.     if(tree != 0)   // if the tree is not null...
  314.     {
  315.         Destroy(tree->left);    // ...first, destroy the left side of the tree (passed in as reference)
  316.         Destroy(tree->right);   // ...then, destroy the right side of the tree
  317.  
  318.         delete tree;            // provides a base to stop the preceding recursive actions
  319.         /**
  320.          * NOTE:
  321.          * After the tree is deleted, only a leaf will be left.
  322.          */
  323.     }
  324. }
  325.  
  326. /**
  327.  * CountNodes() AUXILIARY FUNCTION:
  328.  */
  329. template <class ItemType>
  330. int CountNodes(TreeNode<ItemType> *tree)    // only a pointer is used because the structure of the tree is only going to be recursed and not changed
  331. {
  332.     if(tree == 0)   // if the tree is empty...
  333.     {
  334.         return 0;       // ...report accordingly
  335.     }
  336.     else            // ...
  337.     {
  338.         /**
  339.          * ...return the count of nodes on the left, added to the count of nodes on the right, plus
  340.          * the actual node itself.
  341.          *
  342.          * NOTE:
  343.          * Pay careful attention to the fact that this action is done recursively.
  344.          */
  345.         return(CountNodes(tree->left) + CountNodes(tree->right) + 1);
  346.     }
  347. }
  348.  
  349. /**
  350.  * Insert() AUXILIARY FUNCTION:
  351.  */
  352. template <class ItemType>
  353. void Insert(TreeNode<ItemType> *&tree, ItemType item)
  354. {
  355.     /**
  356.      * NOTE:
  357.      * The TreeNode<ItemType> pointer is provided by reference, because the operations performed in
  358.      * this functions will change it.
  359.      *
  360.      * The result will yield the same tree with the new item (being inserted) added to it.
  361.      */
  362.  
  363.     /**
  364.      * If this is the first item being inserted into the tree, or a point is reached where the item
  365.      * can be inserted:
  366.      */
  367.     if(tree == 0)
  368.     {
  369.         tree = new TreeNode<ItemType>();
  370.         tree->element = item;
  371.         tree->left = 0;                     // because its a leaf
  372.         tree->right = 0;                    // "
  373.     }
  374.     else if(item < tree->element)   // ...
  375.         Insert(tree->left, item);       // ...recursively search for the place on the left side of the tree to insert the item until it's found, then do accordingly
  376.     else                            // the item being inserted is still bigger than the items on the left of the tree...
  377.         Insert(tree->right, item);      // ...recursively search for the place on the right side of the tree to insert the item until it's found, then do accordingly
  378.  
  379.     /**
  380.      * NOTE:
  381.      * In the preceding algorithm, items were inserted into the tree as leaves.  This is not the best
  382.      * approaching.  A better alternative is to work on 'balanced search trees', which will require
  383.      * the implementation of a more complex algorithm.
  384.      *
  385.      * The problem with the aforementioned approach is that, whenever the code searches for an item,
  386.      * because there are more levels, the search will take longer.
  387.      */
  388. }
  389.  
  390. /**
  391.  * Retrieve() AUXILIARY FUNCTION:
  392.  */
  393. template <class ItemType>
  394. void Retrieve(TreeNode<ItemType> *tree, ItemType &item, bool &found)
  395. {
  396.     if(tree == 0)                   // if the tree is empty...
  397.         found = false;                          // ...set the value for found accordingly
  398.     else if(item < tree->element)   // if the item is smaller than the current tree element...
  399.         Retrieve(tree->left, item, found);      // ...recurse on the left side of the tree until the item is found
  400.     else if(item > tree->element)   // if the item is larger than the current tree element...
  401.         Retrieve(tree->right, item, found);     // ...recurse on the right side of the tree until the item is found
  402.     else                            // if the item is equal to the tree element...
  403.     {
  404.         item = tree->element;                   // store its value in the item variable
  405.         found = true;                           // ...
  406.     }
  407. }
  408.  
  409. /**
  410.  * Delete() AUXILIARY FUNCTION:
  411.  */
  412. template <class ItemType>
  413. void Delete(TreeNode<ItemType> *&tree, ItemType item)
  414. {
  415.     if(item < tree->element)        // if the item is smaller than the current tree element...
  416.         Delete(tree->left, item);       // ...recursively search on the left side of the tree until the item is found
  417.     else if(item > tree->element)   // if the item is greater than the current tree element...
  418.         Delete(tree->right, item);      // ...recursively search on the right side of the tree until the item is found
  419.     else                            // if the item is equal to the tree element (if the item is found)...
  420.         DeleteNode(tree);               // ...pass the tree to the DeleteNode() auxiliary function to do the job
  421. }
  422.  
  423. /**
  424.  * DeleteNode() AUXILIARY FUNCTION:
  425.  */
  426. template <class ItemType>
  427. void DeleteNode(TreeNode<ItemType> *&tree)
  428. {
  429.     /**
  430.      * NOTE:
  431.      * To delete a node from the tree, code will be implemented to:
  432.      * - simply delete a node if it has no predecessor/child.
  433.      *
  434.      * - replace a node with its predecessor/child, if it has only one predecessor/child (either a
  435.      * left or right one (but not both)).
  436.      *
  437.      * - replace the node with its left predecessor/child that has the greatest value, making
  438.      * everything on the left still smaller, and everything on the right still larger.
  439.      */
  440.  
  441.     ItemType            data;
  442.     TreeNode<ItemType>  *pTemp = tree;  // create a temporary pointer and make it point to the tree being manipulated
  443.  
  444.         /**
  445.          * if the tree has only 1 child on either side
  446.          */
  447.         if(tree->left == 0)         // if the left part of the tree is null...
  448.         {
  449.             tree = tree->right;                 // ...point the tree to its right child
  450.  
  451.             delete pTemp;                       // ...delete the temporary pointer, deleting the previous tree root
  452.         }
  453.         else if(tree->right == 0)   // if the right part of the tree is null...
  454.         {
  455.             tree = tree->left;                  // ...point the tree to its left child
  456.  
  457.             delete pTemp;                       // ...delete the temporary pointer, deleting the previous tree root
  458.         }
  459.         else                        // if the tree has both children...
  460.         {
  461.             GetPredecessor(tree->left, data);   // ...get the left predecessor of the tree and store its value in the data variable
  462.  
  463.             tree->element = data;               // ...replace the item to be deleted with the data acquired from the tree's predecessor
  464.  
  465.             Delete(tree->left, data);           // ...delete the predecessor containing the previously acquired data
  466.         }
  467. }
  468.  
  469. /**
  470.  * GetPredecessor() AUXILIARY FUNCTION:
  471.  */
  472. template <class ItemType>
  473. void GetPredecessor(TreeNode<ItemType> *tree, ItemType &data)
  474. {
  475.         while(tree->right != 0)     // while the tree has a right node...
  476.             tree = tree->right;         // ...continue to the rightmost node
  477.  
  478.     data = tree->element;           // assign the value of the element of the rightmost node of the tree to the data variable
  479. }
  480.  
  481. /**
  482.  * PreOrder AUXILIARY FUNCTION:
  483.  */
  484. template <class ItemType>
  485. void PreOrder(TreeNode<ItemType> *tree, LinkedQueue<ItemType> &preQueue)
  486. {
  487.     /**
  488.      * NOTE:
  489.      * The code implemented in the PreOrder() function will allow the function to visit the current
  490.      * node first, then all the nodes on the left sub-tree, then all the nodes on the right sub-tree.
  491.      * The process will halt when the tree is null (a null value is reached).
  492.      */
  493.     if(tree != 0)
  494.     {
  495.         preQueue.Enqueue(tree->element);    // add the current element to the linked queue
  496.         PreOrder(tree->left, preQueue);     // (recursively) visit and add all of the items on the left sub-tree to the linked queue
  497.         PreOrder(tree->right, preQueue);    // (recursively) visit and add all of the items on the right sub-tree to the linked queue
  498.     }
  499. }
  500.  
  501. /**
  502.  * InOrder AUXILIARY FUNCTION:
  503.  */
  504. template <class ItemType>
  505. void InOrder(TreeNode<ItemType> *tree, LinkedQueue<ItemType> &inQueue)
  506. {
  507.     /**
  508.      * NOTE:
  509.      * The code implemented in the InOrder() function will allow the function to visit all the nodes
  510.      * on the left sub-tree first, then the current node, then all the nodes on the right sub-tree.
  511.      * The process will halt when the tree is null (a null value is reached).
  512.      */
  513.     if(tree != 0)
  514.     {
  515.         InOrder(tree->left, inQueue);       // (recursively) visit and add all of the items on the left sub-tree to the linked queue
  516.         inQueue.Enqueue(tree->element);     // add the current element to the linked queue
  517.         InOrder(tree->right, inQueue);      // (recursively) visit and add all of the items on the right sub-tree to the linked queue
  518.     }
  519. }
  520.  
  521. /**
  522.  * PostOrder AUXILIARY FUNCTION:
  523.  */
  524. template <class ItemType>
  525. void PostOrder(TreeNode<ItemType> *tree, LinkedQueue<ItemType> &postQueue)
  526. {
  527.     /**
  528.      * NOTE:
  529.      * The code implemented in the PostOrder() function will allow the function to visit all the nodes
  530.      * on the left sub-tree first, then all the nodes on the right sub-tree, then the current node.
  531.      * The process will halt when the tree is null (a null value is reached).
  532.      */
  533.     if(tree != 0)
  534.     {
  535.         PostOrder(tree->left, postQueue);   // (recursively) visit and add all of the items on the left sub-tree to the linked queue
  536.         PostOrder(tree->right, postQueue);  // (recursively) visit and add all of the items on the right sub-tree to the linked queue
  537.         postQueue.Enqueue(tree->element);   // add the current element to the linked queue
  538.     }
  539. }
  540.  
  541. /**
  542.  * Print() AUXILIARY FUNCTION:
  543.  */
  544. template <class ItemType>
  545. void Print(TreeNode<ItemType> *tree)
  546. {
  547.     /**
  548.      * NOTE:
  549.      * To print a tree, the whole left side will be printed first, then the whole right side.  This
  550.      * method is called in-order traverse, and will be implemented using recursion.
  551.      */
  552.     if(tree != 0)
  553.     {
  554.         Print(tree->left);
  555.  
  556.         std::cout << tree->element << std::endl;
  557.  
  558.         Print(tree->right);
  559.     }
  560. }
Advertisement
Add Comment
Please, Sign In to add comment