No Description

main.cpp 9.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. // Binary Search Tree implementation using zybooks algorithms
  2. //
  3. // Rafael Arce Nazario 2019
  4. #define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one cpp file
  5. #include "catch.hpp"
  6. #include <queue>
  7. #include <iostream>
  8. using namespace std;
  9. class BTNode {
  10. public:
  11. int key;
  12. BTNode *left, *right;
  13. BTNode(int k = 0, BTNode *l = NULL, BTNode *r = NULL) : key(k), left(l), right(r) {}
  14. };
  15. class BST {
  16. private:
  17. BTNode *root;
  18. public:
  19. BST(): root(NULL) {}
  20. void insert(int k);
  21. void insertRec(int k);
  22. void insertRec(int k, BTNode *r);
  23. void remove(int k);
  24. void remove(int k, BTNode *r);
  25. void recDisplay(ostream &out) const;
  26. void recDisplay(ostream &out, BTNode *cur, int dist) const;
  27. BTNode *search(int k) const;
  28. BTNode *searchRec(int k) const;
  29. BTNode *searchRec(int k, BTNode *r) const;
  30. int getHeight() const;
  31. int getHeight(BTNode *r) const;
  32. int sum() const;
  33. int sum(BTNode *r) const;
  34. int leafQty() const;
  35. int leafQty(BTNode *n) const;
  36. int parentsOfTwo() const;
  37. int parentsOfTwo(BTNode *n) const;
  38. string InOrder() const;
  39. void InOrder(BTNode *n, string &st) const;
  40. string BFS() const;
  41. };
  42. // function search:
  43. // Given k, a key to search, returns a pointer to the first
  44. // node that contains such key. If not found returns a NULL pointer.
  45. BTNode* BST::search(int k) const {
  46. BTNode* cur = root;
  47. while (cur) {
  48. if (k == cur->key) {return cur;}
  49. // Found
  50. else if (k < cur->key) { cur = cur->left; }
  51. else { cur = cur->right; }
  52. }
  53. return NULL;
  54. }
  55. // function insert:
  56. // Given k, a key to insert, inserts into the BST.
  57. // In this implementation if the key already exists in the tree
  58. // it will be inserted in the RIGHT subtree of the existing key.
  59. void BST::insert(int k) {
  60. BTNode *cur;
  61. BTNode *n = new BTNode(k);
  62. if (!root) {
  63. // This tree is empty, the new node is the root!
  64. root = n;
  65. }
  66. else {
  67. // Lets search the tree for a place to insert....
  68. cur = root;
  69. while (cur) {
  70. if (k < cur->key){
  71. // The value to insert is less than current node
  72. if (cur->left == NULL) {
  73. // If we have reached a node who lacks a left child
  74. // then our new node will be the left child
  75. cur->left = n;
  76. cur = NULL;
  77. }
  78. else {
  79. // keep looking for a place to insert, on the left subtree
  80. cur = cur->left;
  81. }
  82. }
  83. else {
  84. // The value to insert is greater or equal than current node
  85. if (cur->right == NULL){
  86. // If we have reached a node who lacks a right child
  87. // then our new node will be the right child
  88. cur->right = n;
  89. cur = NULL;
  90. }
  91. else {
  92. // keep looking for a place to insert, on the right subtree
  93. cur = cur->right;
  94. }
  95. }
  96. }
  97. }
  98. }
  99. // functions recDisplay:
  100. // Print the tree to the standard output.
  101. void BST::recDisplay(ostream &out) const {
  102. recDisplay(out, root, 0);
  103. }
  104. void BST::recDisplay(ostream &out, BTNode *cur, int dist) const{
  105. if (cur) {
  106. if (cur->right) recDisplay(out, cur->right, dist + 1);
  107. for (int i = 0; i < dist; i++) cout << " ";
  108. out << cur->key << endl;
  109. if (cur->left) recDisplay(out, cur->left, dist + 1);
  110. }
  111. }
  112. // functions remove:
  113. // Given k, a key to remove, removes the first node that it finds with
  114. // such key.
  115. void BST::remove(int k) {
  116. remove(k, root);
  117. }
  118. void BST::remove(int k, BTNode *r) {
  119. BTNode *parent = NULL;
  120. BTNode *cur = r;
  121. while (cur) { // Search for node
  122. if (cur->key == k) { // Node found
  123. if (cur->left == NULL && cur->right == NULL) { // Remove leaf
  124. cout << "cur is a leaf: " << cur->key << endl;
  125. if (!parent) { // Node is root
  126. root = NULL;
  127. }
  128. else if (parent->left == cur)
  129. parent->left = NULL;
  130. else
  131. parent->right = NULL;
  132. delete cur;
  133. }
  134. else if (cur->left && cur->right == NULL) { // Remove node with only left child
  135. if (!parent) // Node is root
  136. root = cur->left;
  137. else if (parent->left == cur)
  138. parent->left = cur->left;
  139. else
  140. parent->right = cur->left;
  141. delete cur;
  142. }
  143. else if (cur->left == NULL && cur->right) { // Remove node with only right child
  144. if (!parent) // Node is root
  145. root = cur->right;
  146. else if (parent->left == cur)
  147. parent->left = cur->right;
  148. else
  149. parent->right = cur->right;
  150. delete cur;
  151. }
  152. else { // Remove node with two children
  153. // Find successor (leftmost child of right subtree)
  154. BTNode *suc = cur->right;
  155. while (suc->left )
  156. suc = suc->left;
  157. int successorData = suc->key;
  158. remove(suc->key, cur); // Remove successor
  159. cur->key = successorData;
  160. }
  161. return; // Node found and removed
  162. }
  163. else if (cur->key < k) { // Search right
  164. parent = cur;
  165. cur = cur->right;
  166. }
  167. else { // Search left
  168. parent = cur;
  169. cur = cur->left;
  170. }
  171. }
  172. return; // Node not found
  173. }
  174. // function getHeight:
  175. // Returns the height of the tree.
  176. int BST::getHeight() const {
  177. return getHeight(root);
  178. }
  179. int BST::getHeight(BTNode *r) const {
  180. if (!r) return -1;
  181. int leftHeight = getHeight(r->left);
  182. int rightHeight = getHeight(r->right);
  183. return 1 + max(leftHeight, rightHeight);
  184. }
  185. // function sum:
  186. // Returns the sum of all keys in the tree.
  187. int BST::sum() const { return sum(root);}
  188. int BST::sum(BTNode *n) const {
  189. if (!n) return 0;
  190. else return n->key + sum(n->left) + sum(n->right);
  191. }
  192. // function leafQty:
  193. // Returns the number of leaves in the tree.
  194. int BST::leafQty() const { return leafQty(root);}
  195. int BST::leafQty(BTNode *n) const {
  196. if (!n) return 0;
  197. if (n->left == NULL && n->right == NULL) return 1;
  198. else return leafQty(n->left) + leafQty(n->right);
  199. }
  200. // function parentsOfTwo:
  201. // Returns the number of nodes that are parents of two children.
  202. int BST::parentsOfTwo() const {
  203. return parentsOfTwo(root);
  204. }
  205. int BST::parentsOfTwo(BTNode *n) const {
  206. if (!n || (!n->left && !n->right)) return 0;
  207. int resultLeft = parentsOfTwo(n->left);
  208. int resultRight = parentsOfTwo(n->right);
  209. if (n->left && n->right) return 1 + resultLeft + resultRight;
  210. else return resultLeft + resultRight;
  211. }
  212. // function InOrder:
  213. // Will return a string containing the sequence of visited keys
  214. // during an in-order traversal (BFS) of the tree.
  215. string BST::InOrder() const {
  216. string st;
  217. InOrder(root, st);
  218. return st;
  219. }
  220. void BST::InOrder(BTNode *n, string &st) const {
  221. if (n) {
  222. InOrder(n->left, st);
  223. st = st + to_string(n->key) + " ";
  224. InOrder(n->right, st);
  225. }
  226. }
  227. // function BFS:
  228. // Will return a string containing the sequence of visited keys
  229. // during a breadth-first traversal of the tree.
  230. string BST::BFS() const {
  231. string st;
  232. queue<BTNode*> q;
  233. if(root!=NULL) q.push(root);
  234. while(!q.empty()) {
  235. BTNode *f = q.front();
  236. st.append(to_string(f->key));
  237. st.append(" ");
  238. if (f->left != NULL) q.push(f->left);
  239. if (f->right != NULL) q.push(f->right);
  240. q.pop();
  241. }
  242. return st;
  243. }
  244. // function searchRec:
  245. // A recursive version of the search algorithm.
  246. BTNode* BST::searchRec(int k) const { return searchRec(k,root); }
  247. BTNode* BST::searchRec(int k, BTNode *r) const {
  248. if (r) {
  249. if (k == r->key) return r;
  250. else if (k < r->key)
  251. return searchRec(k, r->left);
  252. else
  253. return searchRec(k, r->right);
  254. }
  255. return NULL;
  256. }
  257. // function insertRec:
  258. // A recursive version of the insert algorithm.
  259. void BST::insertRec(int k) {
  260. if (!root) root = new BTNode(k);
  261. else insertRec(k, root);
  262. }
  263. void BST::insertRec(int k, BTNode *r) {
  264. if (k < r->key) {
  265. if (r->left == NULL) r->left = new BTNode(k);
  266. else insertRec(k, r->left);
  267. }
  268. else { // k is greater than r->key
  269. if (r->right == NULL) r->right = new BTNode(k);
  270. else insertRec(k, r->right);
  271. }
  272. }
  273. TEST_CASE( "BST is tested", "[BST]" ) {
  274. vector<int> v = {8, 9, 5, 2, 4, 10, 1};
  275. BST B;
  276. for (auto e: v) B.insert(e);
  277. REQUIRE (B.InOrder() == "1 2 4 5 8 9 10 ");
  278. REQUIRE (B.BFS() == "8 5 9 2 10 1 4 ");
  279. }