1 /* 2 File: bst.c 3 Implementation of the binary search tree data structure. 4 5 */ 6 #include <stdlib.h> 7 #include <stdio.h> 8 #include <assert.h> 9 #include "bst.h" 10 #include "structs.h" 11 12 13 struct Node { 14 TYPE val; 15 struct Node *left; 16 struct Node *right; 17 }; 18 19 struct BSTree { 20 struct Node *root; 21 int cnt; 22 }; 23 24 /*----------------------------------------------------------------------------*/ 25 /* 26 function to initialize the binary search tree. 27 param tree 28 pre: tree is not null 29 post: tree size is 0 30 root is null 31 */ 32 33 void initBSTree(struct BSTree *tree) 34 { 35 tree->cnt = 0; 36 tree->root = 0; 37 } 38 39 /* 40 function to create a binary search tree. 41 param: none 42 pre: none 43 post: tree->count = 0 44 tree->root = 0; 45 */ 46 47 struct BSTree* newBSTree() 48 { 49 struct BSTree *tree = (struct BSTree *)malloc(sizeof(struct BSTree)); 50 assert(tree != 0); 51 52 initBSTree(tree); 53 return tree; 54 } 55 56 /*----------------------------------------------------------------------------*/ 57 /* 58 function to free the nodes of a binary search tree 59 param: node the root node of the tree to be freed 60 pre: none 61 post: node and all descendants are deallocated 62 */ 63 64 void _freeBST(struct Node *node) 65 { 66 if (node != 0) { 67 _freeBST(node->left); 68 _freeBST(node->right); 69 free(node); 70 } 71 } 72 73 /* 74 function to clear the nodes of a binary search tree 75 param: tree a binary search tree 76 pre: tree ! = null 77 post: the nodes of the tree are deallocated 78 tree->root = 0; 79 tree->cnt = 0 80 */ 81 void clearBSTree(struct BSTree *tree) 82 { 83 _freeBST(tree->root); 84 tree->root = 0; 85 tree->cnt = 0; 86 } 87 88 /* 89 function to deallocate a dynamically allocated binary search tree 90 param: tree the binary search tree 91 pre: tree != null; 92 post: all nodes and the tree structure itself are deallocated. 93 */ 94 void deleteBSTree(struct BSTree *tree) 95 { 96 clearBSTree(tree); 97 free(tree); 98 } 99 100 /*----------------------------------------------------------------------------*/ 101 /* 102 function to determine if a binary search tree is empty. 103 104 param: tree the binary search tree 105 pre: tree is not null 106 */ 107 int isEmptyBSTree(struct BSTree *tree) { return (tree->cnt == 0); } 108 109 /* 110 function to determine the size of a binary search tree 111 112 param: tree the binary search tree 113 pre: tree is not null 114 */ 115 int sizeBSTree(struct BSTree *tree) { return tree->cnt; } 116 117 /*----------------------------------------------------------------------------*/ 118 /* 119 recursive helper function to add a node to the binary search tree. 120 HINT: You have to use the compare() function to compare values. 121 param: cur the current root node 122 val the value to be added to the binary search tree 123 pre: val is not null 124 */ 125 struct Node *_addNode(struct Node *cur, TYPE val) 126 { 127 cur=newBSTree(); 128 if(cur!=0) 129 { 130 cur->val=val; 131 cur->left=0; 132 cur->right=0; 133 return cur; 134 } 135 return 0; 136 }//program_by_me 137 138 /* 139 function to add a value to the binary search tree 140 param: tree the binary search tree 141 val the value to be added to the tree 142 143 pre: tree is not null 144 val is not null 145 pose: tree size increased by 1 146 tree now contains the value, val 147 */ 148 void addBSTree(struct BSTree *tree, TYPE val) 149 { 150 tree->root = _addNode(tree->root, val); 151 tree->cnt++; 152 } 153 154 155 /* 156 function to determine if the binary search tree contains a particular element 157 HINT: You have to use the compare() function to compare values. 158 param: tree the binary search tree 159 val the value to search for in the tree 160 pre: tree is not null 161 val is not null 162 post: none 163 */ 164 165 /*----------------------------------------------------------------------------*/ 166 int containsBSTree(struct BSTree *tree, TYPE val) 167 { 168 /*write this*/ 169 if(tree!=0) 170 { 171 172 } 173 return 0; 174 } 175 176 /* 177 helper function to find the left most child of a node 178 return the value of the left most child of cur 179 param: cur the current node 180 pre: cur is not null 181 post: none 182 */ 183 184 /*----------------------------------------------------------------------------*/ 185 TYPE _leftMost(struct Node *cur) 186 { 187 /*write this*/ 188 return NULL; 189 } 190 191 192 /* 193 recursive helper function to remove the left most child of a node 194 HINT: this function returns cur if its left child is NOT NULL. Otherwise, 195 it returns the right child of cur and free cur. 196 197 Note: If you do this iteratively, the above hint does not apply. 198 199 param: cur the current node 200 pre: cur is not null 201 post: the left most node of cur is not in the tree 202 */ 203 /*----------------------------------------------------------------------------*/ 204 struct Node *_removeLeftMost(struct Node *cur) 205 { 206 /*write this*/ 207 return NULL; 208 } 209 /* 210 recursive helper function to remove a node from the tree 211 HINT: You have to use the compare() function to compare values. 212 param: cur the current node 213 val the value to be removed from the tree 214 pre: val is in the tree 215 cur is not null 216 val is not null 217 */ 218 /*----------------------------------------------------------------------------*/ 219 struct Node *_removeNode(struct Node *cur, TYPE val) 220 { 221 /*write this*/ 222 return NULL; 223 224 } 225 /* 226 function to remove a value from the binary search tree 227 param: tree the binary search tree 228 val the value to be removed from the tree 229 pre: tree is not null 230 val is not null 231 val is in the tree 232 pose: tree size is reduced by 1 233 */ 234 void removeBSTree(struct BSTree *tree, TYPE val) 235 { 236 if (containsBSTree(tree, val)) { 237 tree->root = _removeNode(tree->root, val); 238 tree->cnt--; 239 } 240 } 241 242 /*----------------------------------------------------------------------------*/ 243 244 /* The following is used only for debugging, set to "#if 0" when used 245 in other applications */ 246 #if 1 247 #include <stdio.h> 248 249 /*----------------------------------------------------------------------------*/ 250 void printNode(struct Node *cur) { 251 if (cur == 0) 252 return; 253 printf("("); 254 printNode(cur->left); 255 /*Call print_type which prints the value of the TYPE*/ 256 print_type(cur->val); 257 printNode(cur->right); 258 printf(")"); 259 } 260 261 void printTree(struct BSTree *tree) { 262 if (tree == 0) 263 return; 264 printNode(tree->root); 265 } 266 /*----------------------------------------------------------------------------*/ 267 268 #endif 269 270 271 /************************************************************************************************************************ 272 from here to the end of this file are a set of fucntions for testing the fucntions of the BST 273 ***************************************************************************************************************************/ 274 /* 275 function to built a Binary Search Tree (BST) by adding numbers in this specific order 276 the graph is empty to start: 50, 13, 110 , 10 277 278 */ 279 struct BSTree *buildBSTTree() { 280 /* 50 281 13 110 282 10 283 */ 284 struct BSTree *tree = newBSTree(); 285 286 /*Create value of the type of data that you want to store*/ 287 struct data *myData1 = (struct data *) malloc(sizeof(struct data)); 288 struct data *myData2 = (struct data *) malloc(sizeof(struct data)); 289 struct data *myData3 = (struct data *) malloc(sizeof(struct data)); 290 struct data *myData4 = (struct data *) malloc(sizeof(struct data)); 291 292 myData1->number = 50; 293 myData1->name = "rooty"; 294 myData2->number = 13; 295 myData2->name = "lefty"; 296 myData3->number = 110; 297 myData3->name = "righty"; 298 myData4->number = 10; 299 myData4->name = "lefty of lefty"; 300 301 /*add the values to BST*/ 302 addBSTree(tree, myData1); 303 addBSTree(tree, myData2); 304 addBSTree(tree, myData3); 305 addBSTree(tree, myData4); 306 307 return tree; 308 } 309 310 /* 311 function to print the result of a test function 312 param: predicate: the result of the test 313 nameTestFunction : the name of the function that has been tested 314 message 315 316 */ 317 void printTestResult(int predicate, char *nameTestFunction, char *message){ 318 if (predicate) 319 printf("%s(): PASS %s\n",nameTestFunction, message); 320 else 321 printf("%s(): FAIL %s\n",nameTestFunction, message); 322 } 323 324 /* 325 fucntion to test each node of the BST and their children 326 327 */ 328 void testAddNode() { 329 struct BSTree *tree = newBSTree(); 330 331 struct data myData1, myData2, myData3, myData4; 332 333 myData1.number = 50; 334 myData1.name = "rooty"; 335 addBSTree(tree, &myData1); 336 //check the root node 337 if (compare(tree->root->val,&myData1) != 0) { 338 printf("addNode() test: FAIL to insert 50 as root\n"); 339 return; 340 } 341 //check the tree->cnt value after adding a node to the tree 342 else if (tree->cnt != 1) { 343 printf("addNode() test: FAIL to increase count when inserting 50 as root\n"); 344 return; 345 } 346 else 347 printf("addNode() test: PASS when adding 50 as root\n"); 348 349 350 myData2.number = 13; 351 myData2.name = "lefty"; 352 addBSTree(tree, &myData2); 353 354 //check the position of the second element that is added to the BST tree 355 if (compare(tree->root->left->val, &myData2) != 0) { 356 printf("addNode() test: FAIL to insert 13 as left child of root\n"); 357 return; 358 } 359 else if (tree->cnt != 2) { 360 printf("addNode() test: FAIL to increase count when inserting 13 as left of root\n"); 361 return; 362 } 363 else 364 printf("addNode() test: PASS when adding 13 as left of root\n"); 365 366 367 myData3.number = 110; 368 myData3.name = "righty"; 369 addBSTree(tree, &myData3); 370 371 //check the position of the third element that is added to the BST tree 372 if (compare(tree->root->right->val, &myData3) != 0) { 373 printf("addNode() test: FAIL to insert 110 as right child of root\n"); 374 return; 375 } 376 else if (tree->cnt != 3) { 377 printf("addNode() test: FAIL to increase count when inserting 110 as right of root\n"); 378 return; 379 } 380 else 381 printf("addNode() test: PASS when adding 110 as right of root\n"); 382 383 myData4.number = 10; 384 myData4.name = "righty of lefty"; 385 addBSTree(tree, &myData4); 386 387 //check the position of the fourth element that is added to the BST tree 388 if (compare(tree->root->left->left->val, &myData4) != 0) { 389 printf("addNode() test: FAIL to insert 10 as left child of left of root\n"); 390 return; 391 } 392 else if (tree->cnt != 4) { 393 printf("addNode() test: FAIL to increase count when inserting 10 as left of left of root\n"); 394 return; 395 } 396 else 397 printf("addNode() test: PASS when adding 10 as left of left of root\n"); 398 399 printf("Deleting the BSTree...\n"); 400 deleteBSTree(tree); 401 printf("Returning from testAddNode().\n"); 402 } 403 404 /* 405 fucntion to test that the BST contains the elements that we added to it 406 407 */ 408 void testContainsBSTree() { 409 struct BSTree *tree = buildBSTTree(); 410 411 struct data myData1, myData2, myData3, myData4, myData5; 412 413 myData1.number = 50; 414 myData1.name = "rooty"; 415 myData2.number = 13; 416 myData2.name = "lefty"; 417 myData3.number = 110; 418 myData3.name = "righty"; 419 myData4.number = 10; 420 myData4.name = "lefty of lefty"; 421 myData5.number = 111; 422 myData5.name = "not in tree"; 423 424 printTestResult(containsBSTree(tree, &myData1), "containsBSTree", "when test containing 50 as root"); 425 426 printTestResult(containsBSTree(tree, &myData2), "containsBSTree", "when test containing 13 as left of root"); 427 428 printTestResult(containsBSTree(tree, &myData3), "containsBSTree", "when test containing 110 as right of root"); 429 430 printTestResult(containsBSTree(tree, &myData4), "containsBSTree", "when test containing 10 as left of left of root"); 431 432 //check containsBSTree fucntion when the tree does not contain a node 433 printTestResult(!containsBSTree(tree, &myData5), "containsBSTree", "when test containing 111, which is not in the tree"); 434 435 printf("Deleting the BSTree...\n"); 436 deleteBSTree(tree); 437 printf("Returning from testContainsBSTree().\n"); 438 439 } 440 441 /* 442 fucntion to test the left_Most_element 443 444 */ 445 void testLeftMost() { 446 struct BSTree *tree = buildBSTTree(); 447 448 struct data myData3, myData4; 449 450 myData3.number = 110; 451 myData3.name = "righty"; 452 myData4.number = 10; 453 myData4.name = "lefty of lefty"; 454 455 printTestResult(compare(_leftMost(tree->root), &myData4) == 0, "_leftMost", "left most of root"); 456 457 printTestResult(compare(_leftMost(tree->root->left), &myData4) == 0, "_leftMost", "left most of left of root"); 458 459 printTestResult(compare(_leftMost(tree->root->left->left), &myData4) == 0, "_leftMost", "left most of left of left of root"); 460 461 printTestResult(compare(_leftMost(tree->root->right), &myData3) == 0, "_leftMost", "left most of right of root"); 462 463 printf("Deleting the BSTree...\n"); 464 deleteBSTree(tree); 465 printf("Returning from testLeftMost().\n"); 466 467 } 468 469 void testRemoveLeftMost() { 470 struct BSTree *tree = buildBSTTree(); 471 struct Node *cur; 472 473 cur = _removeLeftMost(tree->root); 474 475 printTestResult(cur == tree->root, "_removeLeftMost", "removing leftmost of root 1st try"); 476 477 cur = _removeLeftMost(tree->root->right); 478 printTestResult(cur == NULL, "_removeLeftMost", "removing leftmost of right of root 1st try"); 479 480 cur = _removeLeftMost(tree->root); 481 printTestResult(cur == tree->root, "_removeLeftMost", "removing leftmost of root 2st try"); 482 } 483 484 void testRemoveNode() { 485 struct BSTree *tree = buildBSTTree(); 486 struct Node *cur; 487 struct data myData1, myData2, myData3, myData4; 488 489 myData1.number = 50; 490 myData1.name = "rooty"; 491 myData2.number = 13; 492 myData2.name = "lefty"; 493 myData3.number = 110; 494 myData3.name = "righty"; 495 myData4.number = 10; 496 myData4.name = "lefty of lefty"; 497 498 _removeNode(tree->root, &myData4); 499 printTestResult(compare(tree->root->val, &myData1) == 0 && tree->root->left->left == NULL, "_removeNode", "remove left of left of root 1st try"); 500 501 _removeNode(tree->root, &myData3); 502 printTestResult(compare(tree->root->val, &myData1) == 0 && tree->root->right == NULL, "_removeNode", "remove right of root 2st try"); 503 504 _removeNode(tree->root, &myData2); 505 printTestResult(compare(tree->root->val, &myData1) == 0 && tree->root->left == 0, "_removeNode", "remove right of root 3st try"); 506 507 cur = _removeNode(tree->root, &myData1); 508 printTestResult(cur == NULL, "_removeNode", "remove right of root 4st try"); 509 } 510 511 /* 512 513 Main function for testing different fucntions of the Assignment#4. 514 515 */ 516 517 int main(int argc, char *argv[]){ 518 519 //After implementing your code, please uncommnet the following calls to the test functions and test your code 520 521 // testAddNode(); 522 523 printf("\n"); 524 // testContainsBSTree(); 525 526 printf("\n"); 527 //testLeftMost(); 528 529 printf("\n"); 530 //testRemoveLeftMost(); 531 532 printf("\n"); 533 //testRemoveNode(); 534 535 return 0; 536 }