Advertisement
Guest User

Untitled

a guest
May 30th, 2017
171
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 18.16 KB | None | 0 0
  1. //==========================================================================
  2. //// cs12xia Homework 8 Arvin Bhattacharya
  3. ////--------------------------------------------------------------------------
  4. //// File: Tree.c
  5. ////
  6. //// Description: Contains the Node structure and the member functions of
  7. //// the Tree class.
  8. ////==========================================================================
  9.  
  10. #include <cstdlib>
  11. #include <string>
  12. #include "Tree.h"
  13. using namespace std;
  14.  
  15. // messages
  16. static const char AND[] = " and ";
  17. static const char CHECK[] = " - Checking ";
  18. static const char COMPARE[] = " - Comparing ";
  19. static const char DEALLOCATE[] = " - Deallocating]\n";
  20. static const char INSERT[] = " - Inserting ";
  21. static const char REPLACE[] = " - Replacing ";
  22. static const char UPDATE[] = " - Updating ";
  23.  
  24. template <class Whatever>
  25. int Tree<Whatever>::debug = 0;
  26.  
  27. #ifndef TRUE
  28. #define TRUE 1
  29. #endif
  30.  
  31. #ifndef FALSE
  32. #define FALSE 0
  33. #endif
  34.  
  35. #define THRESHOLD 2
  36.  
  37. template <class Whatever>
  38. ostream & operator << (ostream &, const TNode<Whatever> &);
  39.  
  40. /**
  41. * Description: Defines the fields of TNode
  42. *
  43. * Fields:
  44. * balance - the balance of the node (lheight - rheight, -1 for null child)
  45. * data - the info the node stores
  46. * height - the height of the node (1 + child node height)
  47. * left - the left child
  48. * occupancy - the number of nodes in the tree
  49. * right - the right child
  50. * tree_count - the number of trees made
  51. *
  52. * delete_AllTNodes - clears the tree of all TNodes
  53. * Insert - Inserts a TNode into the tree
  54. * lookup - searches tree to see if a certain node is in the tree
  55. * Remove - Removes a node from the tree
  56. * RemoveAndReplaceMax - handles two child removal case
  57. * SetHeightAndBalance - sets height and balance for each node in the tree
  58. * Write_AllTNodes - writes all TNodes in the tree
  59. */
  60. template <class Whatever>
  61. struct TNode {
  62. long balance;
  63. Whatever data;
  64. long height;
  65. TNode<Whatever> * left;
  66. long & occupancy;
  67. TNode<Whatever> * right;
  68. unsigned long & tree_count;
  69.  
  70. /**
  71. * Description: Ctor which initializes the TNode fields and increments
  72. * occupancy
  73. */
  74. TNode (const Whatever & element, Tree<Whatever> & theTree)
  75. : balance (0), data (element), height (0), left (0),
  76. occupancy (theTree.occupancy), right (0),
  77. tree_count (theTree.tree_count) {
  78. //increment occupancy since new tnode made
  79. occupancy++;
  80. }
  81.  
  82. /**
  83. * Description: Ctor which initializes the TNode fields and increments
  84. * occupancy
  85. */
  86. TNode (const Whatever & element, TNode<Whatever> & parentTNode)
  87. : balance (0), data (element), height (0), left (0),
  88. occupancy (parentTNode.occupancy), right (0),
  89. tree_count (parentTNode.tree_count) {
  90. //increment occupancy since new tnode made
  91. occupancy++;
  92. }
  93.  
  94. /**
  95. * Description: Destructor which decrements occupancy
  96. */
  97. ~TNode (void) {
  98. //decrement occupancy since tnode destroyed
  99. occupancy--;
  100. }
  101.  
  102. /**
  103. * Description: Delete all nodes in the tree
  104. *
  105. * Parameters: None
  106. *
  107. * Returns: None
  108. */
  109. void delete_AllTNodes (void) {
  110. //if there is a left child, recursive call
  111. if (left)
  112. left->delete_AllTNodes ();
  113.  
  114. //if there is a right child, recursive call
  115. if (right)
  116. right->delete_AllTNodes ();
  117.  
  118. //delete this node
  119. delete(this);
  120. }
  121.  
  122. /**
  123. * Description: Inserts a node into the tree
  124. *
  125. * Parameters: element - the element to insert
  126. * PointerInParent - the node to insert from
  127. *
  128. * Returns: True after successful insert
  129. */
  130. unsigned long Insert (const Whatever & element,
  131. TNode<Whatever> *& PointerInParent) {
  132. if (element == PointerInParent->data) { //inserting a duplicate
  133. //return true since successful "insert"
  134. return true;
  135. } else if (element > this->data) { //if element is greater
  136. //debug statement
  137. if (Tree<Whatever> :: debug) {
  138. cerr << TREE << tree_count << COMPARE << element << AND <<
  139. this->data << "]" << endl;
  140. }
  141.  
  142. //check if right node is null
  143. if (!PointerInParent->right) {
  144. //debug statement
  145. if (Tree<Whatever> :: debug) {
  146. cerr << TREE << tree_count << INSERT << element << "]" << endl;
  147. }
  148.  
  149. //insert at right node if it is null
  150. PointerInParent->right = new TNode<Whatever> (element, *this);
  151. } else {
  152. //recursively iterate through tree if right node isnt null
  153. PointerInParent->right->Insert(element, PointerInParent->right);
  154. }
  155. } else { //if element is less
  156. //check if left node is null
  157. if (!PointerInParent->left) {
  158. //debug statement
  159. if (Tree<Whatever> :: debug) {
  160. cerr << TREE << tree_count << INSERT << element << "]" << endl;
  161. }
  162.  
  163. //insert at left node if it is null
  164. PointerInParent->left = new TNode<Whatever> (element, *this);
  165. } else {
  166. //recursively iterate through tree if left node isnt null
  167. PointerInParent->left->Insert(element, PointerInParent->left);
  168. }
  169. }
  170.  
  171. //return true since successful insert
  172. return true;
  173. }
  174.  
  175. /**
  176. * Description: Searches Tree to see if passed in element is in it
  177. *
  178. * Parameters: element - the element to search for
  179. *
  180. * Returns: True if found, false otherwise
  181. */
  182. unsigned long Lookup(Whatever & element) const {
  183. const TNode<Whatever> * working = this; //used to iterate through tree
  184.  
  185. //iterate thorugh tree
  186. while (working) {
  187. //debug statement
  188. if (Tree<Whatever> :: debug) {
  189. cerr << TREE << tree_count << COMPARE << element << AND <<
  190. working->data << "]" << endl;
  191. }
  192.  
  193. //if element and working->data are equal
  194. if (element == working->data) {
  195. //return true since found
  196. return true;
  197. } else if (element > working->data) {
  198. //traverse down right if element is greater than working
  199. working = working->right;
  200. } else {
  201. //traverse down left if element is less than working
  202. working = working->left;
  203. }
  204. }
  205.  
  206. //reach here only if node isnt found
  207. return false;
  208. }
  209.  
  210. /**
  211. * Description: Used to handle removal of a node which has two children
  212. *
  213. * Parameters: targetTNode - the node to remove
  214. * PointerInParent - the node used for recursive
  215. * calls through the tree
  216. *
  217. * Returns - None
  218. */
  219. void ReplaceAndRemoveMax (TNode<Whatever> & targetTNode,
  220. TNode<Whatever> *& PointerInParent) {
  221. TNode<Whatever> * temp = PointerInParent;
  222. TNode<Whatever> * temp_parent;
  223. bool hadLeft = false; //keep track of if node had a left child
  224. bool parentFound = false; //keep track of if parent node found
  225.  
  226. //Predecessor algorithm
  227. temp = temp->left;
  228. while (temp->right) {
  229. //checking for when parent of predecessor reached
  230. if (temp->right && !temp->right->right) {
  231. //store parent of predecessor node
  232. temp_parent = temp;
  233.  
  234. //if the node has a left child
  235. if (temp->right->left) {
  236. //use single child insertion algorithm
  237. temp_parent->right = temp->right->left;
  238.  
  239. //turn had left flag on
  240. hadLeft = true;
  241. }
  242.  
  243. //turn parentfound flag on
  244. parentFound = true;
  245. }
  246.  
  247. //iterate through tree
  248. temp = temp->right;
  249. }
  250.  
  251. //replace the target node's data with predecessor's data
  252. targetTNode.data = temp->data;
  253.  
  254. if (!hadLeft && parentFound) { //if no left child and had parent
  255. //set the parent's right node to NULL
  256. temp_parent->right = NULL;
  257.  
  258. //delete the parent
  259. delete temp_parent;
  260.  
  261. //set parent to NULL
  262. temp_parent = NULL;
  263. } else if (hadLeft && parentFound) { //if left child and had parent
  264. //delete parent
  265. delete temp_parent;
  266.  
  267. //set parent to NULL
  268. temp_parent = NULL;
  269. } else if (!hadLeft && !parentFound) { //if no left child & no parent
  270. //delete left child
  271. delete targetTNode.left;
  272.  
  273. //set left child to NULL
  274. targetTNode.left = NULL;
  275. }
  276. }
  277.  
  278. /**
  279. * Description: Removes elementTNode from the tree if it exists in the tree
  280. *
  281. * Parameters: elementTNode - the node to remove
  282. * PointerInParent - used for recursive calls
  283. *
  284. * Returns: True if successful removal, false otherwise
  285. */
  286. unsigned long Remove (TNode<Whatever> & elementTNode,
  287. TNode<Whatever> *& PointerInParent,
  288. long fromSHB = false) {
  289.  
  290. //if element is not in the tree
  291. if (!Lookup(elementTNode.data)) {
  292. return false;
  293. }
  294.  
  295. if (elementTNode.data == PointerInParent->data) {
  296. //node has 0 children
  297. if (!PointerInParent->left && !PointerInParent->right) {
  298. //delete this node since it has no children
  299. delete PointerInParent;
  300.  
  301. PointerInParent = NULL;
  302. } else if (PointerInParent>left && !PointerInParent->right) {
  303. //node only has left child
  304. TNode<Whatever> * temp = PointerInParent->left;
  305.  
  306. //point to left child
  307. PointerInParent = temp;
  308. delete temp;
  309. } else if (!PointerInParent->left && PointerInParent->right) {
  310. //node only has right child
  311. TNode<Whatever> * temp = PointerInParent->right;
  312.  
  313. //point to right child
  314. PointerInParent = temp;
  315. /*for (int i = 0; i < 3; i++) {
  316. cerr << "node " << i << " is " << PointerInParent->data << endl;
  317. PointerInParent = PointerInParent->right;
  318. } */
  319. //cerr << "PIP IN REMOVE METHOD IS " << PointerInParent->data << endl;
  320.  
  321. //delete temp only if not being called from SHB in order to avoid double
  322. //delete
  323. if (!fromSHB) {
  324. delete temp;
  325. }
  326. } else if (this->left && this->right) { //node has two children
  327. ReplaceAndRemoveMax(*PointerInParent, PointerInParent);
  328. }
  329. } else if (elementTNode.data > PointerInParent->data) { //elem is greater
  330. //recursive call with PointerInParent's right
  331. return Remove(elementTNode, PointerInParent->right);
  332. } else { //elem is less
  333. //recursive call with PointerInParent's left
  334. return Remove(elementTNode, PointerInParent->left);
  335. }
  336.  
  337. //return true since successful removal
  338. return true;
  339. }
  340.  
  341. /**
  342. * Description: Recursively set height and balane values of each node in the
  343. * tree and reshape tree if it grows to be out of balance
  344. *
  345. * Parameters: PointerInParent - the node used to recurse through tree
  346. *
  347. * Returns: None
  348. */
  349. void SetHeightAndBalance (TNode<Whatever> *& PointerInParent) {
  350. if (!PointerInParent->left && !PointerInParent->right) { //base case
  351. height = 0;
  352. balance = 0;
  353. } else {
  354. if (PointerInParent->left && PointerInParent->right) { //two child
  355. if (PointerInParent->left->height >
  356. PointerInParent->right->height) { //if left height greater
  357.  
  358. //recursive call with PIP left child
  359. SetHeightAndBalance(PointerInParent->left);
  360.  
  361. //set height of this node to 1 + updated value of child node height
  362. PointerInParent->height = 1 + PointerInParent->left->height;
  363. } else { //if right height greater
  364.  
  365. //recursive call with PIP right child
  366. SetHeightAndBalance(PointerInParent->right);
  367.  
  368. //set height of this node to 1 + updated value of child node height
  369. PointerInParent->height = 1 + PointerInParent->right->height;
  370. }
  371.  
  372. PointerInParent->balance = PointerInParent->left->height -
  373. PointerInParent->right->height;
  374.  
  375. //TODO CHECK FOR BALANCE THRESHOLD HERE
  376. if (PointerInParent->balance >= THRESHOLD ||
  377. PointerInParent->balance <= -THRESHOLD) {
  378. const Whatever & temp = PointerInParent->data;
  379. TNode<Whatever> * tempNode = this;
  380. Remove(*PointerInParent, tempNode);
  381. Insert(temp, tempNode);
  382. delete tempNode;
  383. }
  384.  
  385. } else if (PointerInParent->left && !PointerInParent->right) {
  386. SetHeightAndBalance(PointerInParent->left);
  387.  
  388. PointerInParent->height = 1 + PointerInParent->left->height;
  389. PointerInParent->balance = PointerInParent->left->height + 1;
  390.  
  391. //TODO CHECK FOR BALANCE THRESHOLD HERE
  392. if (PointerInParent->balance >= THRESHOLD ||
  393. PointerInParent->balance <= -THRESHOLD) {
  394. const Whatever & temp = PointerInParent->data;
  395. TNode<Whatever> * tempNode = this;
  396. Remove(*PointerInParent, tempNode);
  397. Insert(temp, tempNode);
  398. delete tempNode;
  399. }
  400. } else if (!PointerInParent->left && PointerInParent->right) {
  401. SetHeightAndBalance(PointerInParent->right);
  402. PointerInParent->height = 1 + PointerInParent->right->height;
  403. PointerInParent->balance = -1 - PointerInParent->right->height;
  404.  
  405. //TODO CHECK FOR BALANCE THRESHOLD HERE
  406. if (PointerInParent->balance > THRESHOLD ||
  407. PointerInParent->balance < -THRESHOLD) {
  408. const Whatever & temp = PointerInParent->data;
  409.  
  410. TNode<Whatever> * tempNode = this;
  411.  
  412. Remove(*PointerInParent, tempNode, true);
  413. SetHeightAndBalance(tempNode);
  414. Write_AllTNodes(cerr << "The nodes are\n");
  415. //Insert(temp, tempNode);
  416.  
  417. delete tempNode;
  418. }
  419. }
  420. }
  421. }
  422.  
  423. ostream & Write_AllTNodes (ostream & stream) const {
  424. if (left)
  425. left->Write_AllTNodes (stream);
  426. stream << *this;
  427. if (right)
  428. right->Write_AllTNodes (stream);
  429.  
  430. return stream;
  431. }
  432. };
  433.  
  434. /**
  435. * Desccription: Turns debug flag on
  436. *
  437. * Parameters: None
  438. *
  439. * Returns: None
  440. */
  441. template <class Whatever>
  442. void Tree<Whatever> :: Set_Debug_On(void) {
  443. //turn debug flag on
  444. Tree<Whatever> :: debug = true;
  445. }
  446.  
  447. /**
  448. * Description: Turns debug flag off
  449. *
  450. * Paramters: None
  451. *
  452. * Returns: None
  453. */
  454. template <class Whatever>
  455. void Tree<Whatever> :: Set_Debug_Off(void) {
  456. //turn debug flag off
  457. Tree<Whatever> :: debug = false;
  458. }
  459.  
  460. template <class Whatever>
  461. ostream & operator << (ostream & stream, const TNode<Whatever> & nnn) {
  462. stream << "at height: :" << nnn.height << " with balance: "
  463. << nnn.balance << " ";
  464. return stream << nnn.data << "\n";
  465. }
  466.  
  467. /**
  468. * Description: Tree's Insert Method; handles insertion of root node, delegates
  469. * rest to TNode's insert
  470. *
  471. * Parameters: element - element to insert
  472. *
  473. * Returns: True after successful insert
  474. */
  475. template <class Whatever>
  476. unsigned long Tree<Whatever> :: Insert (const Whatever & element) {
  477. //inserting first node
  478. if (root == NULL) {
  479. root = new TNode<Whatever>(element, *this);
  480. } else {
  481. //delegate to TNode's insert
  482. root->Insert(element, root);
  483. }
  484.  
  485. //set height and balance of each node in tree
  486. root->SetHeightAndBalance(root);
  487.  
  488. //return true since successful insert
  489. return true;
  490. }
  491.  
  492. /**
  493. * Description: Delegates to TNode's lookup
  494. *
  495. * Parameters: element - the element to lookup
  496. *
  497. * Returns: True if element is in the table, false otherwise
  498. */
  499. template <class Whatever>
  500. unsigned long Tree<Whatever> :: Lookup (Whatever & element) const {
  501. //delegate lookup to TNode's method
  502. return root->Lookup(element);
  503. }
  504.  
  505. /**
  506. * Description: Removes node if there is only one in the tree, delegates task to
  507. * TNode's removal otherwise
  508. *
  509. * Parameters: element - the element to remove
  510. *
  511. * Returns: True if successful delete, false otherwise
  512. */
  513. template <class Whatever>
  514. unsigned long Tree<Whatever> :: Remove (Whatever & element) {
  515. bool removed = true;
  516.  
  517. //if removing from empty tree
  518. if (root == NULL) {
  519. removed = false;
  520. } else if (Tree<Whatever> :: occupancy == 1) { //if only 1 node in tree
  521. //delete root since it is the only node in tree
  522. delete root;
  523. root = NULL;
  524. } else {
  525. //used for TNode remove recursive call
  526. TNode<Whatever> * temp = new TNode<Whatever>(element, *this);
  527.  
  528. //store result of recursive call here
  529. removed = root->Remove(*temp, root);
  530.  
  531. //delete the temp variable usedfor calling TNode's remove
  532. delete temp;
  533. }
  534.  
  535. //if there is at least one node in tree
  536. if (occupancy > 0) {
  537. //set height and balance of all the nodes in the tree
  538. root->SetHeightAndBalance(root);
  539. }
  540.  
  541. //return result of removal attempt
  542. return removed;
  543. }
  544.  
  545. /***************************************************************************
  546. % Routine Name : Tree<Whatever> :: Tree (public)
  547. % File : Tree.c
  548. %
  549. % Description : Guarantee initialization of occupancy and root. It also
  550. % initializes the tree_count using a static counter.
  551. ***************************************************************************/
  552. template <class Whatever>
  553. Tree<Whatever> :: Tree (void): occupancy (0), root (NULL)
  554.  
  555. {
  556. static long counter;
  557. tree_count = ++counter;
  558. }
  559.  
  560. template <class Whatever>
  561. Tree<Whatever> :: ~Tree (void)
  562. /***************************************************************************
  563. % Routine Name : Tree<Whatever> :: ~Tree (public)
  564. % File : Tree.c
  565. %
  566. % Description : deallocates memory associated with the Tree. It
  567. % will also delete all the memory of the elements within
  568. % the table.
  569. ***************************************************************************/
  570.  
  571. {
  572. //delete all nodes in the tree if there are nodes in the tree
  573. if (root != NULL) {
  574. root->delete_AllTNodes();
  575. }
  576. }
  577.  
  578.  
  579. template <class Whatever>
  580. ostream & Tree<Whatever> :: Write (ostream & stream) const
  581. /***************************************************************************
  582. % Routine Name : Tree<Whatever> :: Write (public)
  583. % File : Tree.c
  584. %
  585. % Description : This function will output the contents of the Tree table
  586. % to the stream specificed by the caller. The stream could be
  587. % cerr, cout, or any other valid stream.
  588. %
  589. % Parameters descriptions :
  590. %
  591. % name description
  592. % ------------------ ------------------------------------------------------
  593. % stream A reference to the output stream.
  594. % <return> A reference to the output stream.
  595. ***************************************************************************/
  596.  
  597. {
  598. stream << "Tree " << tree_count << ":\n"
  599. << "occupancy is " << occupancy << " elements.\n";
  600.  
  601. return (root) ? root->Write_AllTNodes (stream) : stream;
  602. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement