├── .idea ├── .gitignore ├── aws.xml ├── misc.xml ├── modules.xml ├── vcs.xml └── workspace.xml ├── Binary-Search-Tree-DSA.iml ├── BinarySearchTree.java ├── Main.java ├── Node.java ├── README.md └── out └── production └── Binary-Search-Tree-DSA ├── .idea ├── .gitignore ├── misc.xml ├── modules.xml └── vcs.xml ├── Binary-Search-Tree-DSA.iml ├── BinarySearchTree.class ├── Main.class ├── Node.class └── README.md /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /.idea/aws.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 20 | 21 | 23 | { 24 | "lastFilter": { 25 | "state": "OPEN", 26 | "assignee": "hoangsonww" 27 | } 28 | } 29 | { 30 | "selectedUrlAndAccountId": { 31 | "url": "https://github.com/hoangsonww/Binary-Search-Tree-DSA.git", 32 | "accountId": "7aed4cc4-2c10-4afd-b1b1-f9443cf32ff5" 33 | } 34 | } 35 | 36 | 38 | { 39 | "associatedIndex": 1 40 | } 41 | 42 | 43 | 44 | 47 | { 48 | "keyToString": { 49 | "ASKED_SHARE_PROJECT_CONFIGURATION_FILES": "true", 50 | "Application.Main.executor": "Run", 51 | "RunOnceActivity.OpenProjectViewOnStart": "true", 52 | "RunOnceActivity.ShowReadmeOnStart": "true", 53 | "SHARE_PROJECT_CONFIGURATION_FILES": "true", 54 | "git-widget-placeholder": "main", 55 | "ignore.virus.scanning.warn.message": "true", 56 | "kotlin-language-version-configured": "true", 57 | "node.js.detected.package.eslint": "true", 58 | "node.js.detected.package.tslint": "true", 59 | "node.js.selected.package.eslint": "(autodetect)", 60 | "node.js.selected.package.tslint": "(autodetect)", 61 | "nodejs_package_manager_path": "npm", 62 | "settings.editor.selected.configurable": "preferences.general", 63 | "vue.rearranger.settings.migration": "true" 64 | } 65 | } 66 | 67 | 68 | 69 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 1707720651756 79 | 87 | 88 | 95 | 96 | 103 | 106 | 107 | 109 | 110 | 111 | 113 | -------------------------------------------------------------------------------- /Binary-Search-Tree-DSA.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /BinarySearchTree.java: -------------------------------------------------------------------------------- 1 | /** 2 | * A class that represents a Binary Search Tree and its associated methods. 3 | * @author David Nguyen 4 | * @since 03/08/2023 5 | */ 6 | public class BinarySearchTree { 7 | 8 | // A field that represents the root of the Binary Search Tree 9 | private Node root; 10 | 11 | // A field that represents the number of nodes visited when traversing the binary search tree (used for the delete method) 12 | private int numNodesVisited; 13 | 14 | // CONSTRUCTORS: // 15 | 16 | /** 17 | * A constructor that creates a Binary Search Tree that takes no input (A B.S.T. can be created in two main ways, either 18 | * with an input assigned as it root when it's created, or with no inputs and the tree will be created as an empty tree.) 19 | * A Binary Search Tree can be created in three ways in order to allow for the flexibility of creating the tree. 20 | * 21 | */ 22 | public BinarySearchTree() { 23 | this.root = null; 24 | // The number of nodes visited field will always be reset upon the creation of the new tree 25 | this.numNodesVisited = 0; 26 | } 27 | 28 | /** 29 | * A constructor that creates a Binary Search Tree that takes one int input and assigns it as the tree's root by 30 | * creating a node with the parsed-in, given key and making it the root node of the B.S.T. 31 | * (A B.S.T. can be created in two main ways, either with an input assigned as it root when it's created, 32 | * or with no inputs and the tree will be created as an empty tree.) 33 | * A Binary Search Tree can be created in three ways in order to allow for the flexibility of creating the tree. 34 | * 35 | * @param root A root for the tree to be created, parsed in as an integer and a new node will be automatically created 36 | * for that root. 37 | */ 38 | public BinarySearchTree(int root) { 39 | this.root = new Node(root); 40 | // The number of nodes visited field will always be reset upon the creation of the new tree 41 | this.numNodesVisited = 0; 42 | } 43 | 44 | /** 45 | * A constructor that creates a Binary Search Tree that takes one Node input and assigns it as the tree's root. 46 | * (A B.S.T. can be created in two main ways, either with an input assigned as it root when it's created, 47 | * or with no inputs and the tree will be created as an empty tree.) 48 | * A Binary Search Tree can be created in three ways in order to allow for the flexibility of creating the tree. 49 | * 50 | * @param root A root node for the tree to be created, parsed in as a created node 51 | */ 52 | public BinarySearchTree(Node root) { 53 | this.root = root; 54 | // The number of nodes visited field will always be reset upon the creation of the new tree 55 | this.numNodesVisited = 0; 56 | } 57 | 58 | // PRIMARY METHODS: // 59 | 60 | /** 61 | * A method that inserts the specified key into the Binary Search Tree by calling another helper, overloaded method 62 | * with the same name. 63 | * 64 | * @param key A key that will be inserted into the tree. 65 | */ 66 | public void insert(int key) { 67 | insert(this.root, key); 68 | } 69 | 70 | /** 71 | * A method that creates a tree from a given, parsed-in array of integers. Any existing tree will be overwritten. 72 | * 73 | * @param values any given array from which a tree will be created from 74 | */ 75 | public void createTree(int[] values) { 76 | // Now creates a new root for the new tree with the first value of the given array and override the current root 77 | Node newRoot = new Node(values[0]); 78 | // Assign the new root to be the newly-created node 79 | this.root = newRoot; 80 | /* 81 | * A loop that passes every element of the given array into the tree using the insert() method above. It 82 | * will stop when the end of the array is reached. 83 | */ 84 | for (int i = 1; i < values.length; i++) { 85 | insert(newRoot, values[i]); 86 | } 87 | /* 88 | * Now, print out a confirmation that a new tree is created and print out the new tree using three different types 89 | * of traversal. This is done to help with the testing and behavior verification part of this method. 90 | */ 91 | System.out.println("A new tree has been successfully created from the given array:"); 92 | System.out.println("Inorder traversal of the new tree: "); 93 | inorderRec(newRoot); 94 | System.out.println(); 95 | System.out.println("Preorder traversal of the new tree: "); 96 | preorderRec(newRoot); 97 | System.out.println(); 98 | System.out.println("Postorder traversal of the new tree: "); 99 | postorderRec(newRoot); 100 | /* 101 | * When these statements to print the tree are executed, it means that the tree is created successfully from the 102 | * given array, and the programmer can use the information printed on the screen to verify the elements of the tree. 103 | */ 104 | } 105 | 106 | /** 107 | * A method that searches for a specific key in the Binary Search Tree by calling another helper, overloaded method 108 | * with the same name. 109 | * (I have implemented this function before the assignment was changed and therefore, my helper method still returns 110 | * a node with the specified key.) Please forgive me for this mistake. 111 | * @param key A key in the B.S.T. to search for. 112 | * @return A node that is found with the given key, or may return null if no node with such key is found 113 | */ 114 | public boolean search(int key) { 115 | // A Node variable that will be assigned and store the result of the search() helper function 116 | Node searchResult = null; 117 | // A variable that stores the boolean variable true-false for returning 118 | boolean result = true; 119 | // Perform a search that returns a node with the specified key 120 | searchResult = search(this.root, key); 121 | // Checks if the returned node is null. If it is, it means that no nodes with such key is found, return false. 122 | if (searchResult == null) { 123 | result = false; 124 | } 125 | // Simply return this result variable, which can either be true or false 126 | return result; 127 | } 128 | 129 | /** 130 | * A method that deletes the node with the specified key from the Binary Search Tree by calling another helper, 131 | * overloaded method with the same name. 132 | * 133 | * @param key The key of the node that will be deleted from the tree. 134 | * @return The node that is the new root of the new tree after deletion. 135 | */ 136 | public Node delete(int key) { 137 | // A Node variable that will be assigned and store the result of the helper function delete() 138 | Node newRoot = null; 139 | newRoot = delete(this.root, key); 140 | // Simply return this result variable 141 | return newRoot; 142 | } 143 | 144 | /** 145 | * A method that traverses the tree in inorder traversal using recursion and prints out all the nodes while traversing 146 | * by calling another helper, overloaded method with the same name. 147 | */ 148 | public void inorderRec() { 149 | inorderRec(this.root); 150 | } 151 | 152 | /** 153 | * A method that traverses the tree in preorder traversal using recursion and prints out all the nodes while traversing 154 | * by calling another helper, overloaded method with the same name. 155 | */ 156 | public void preorderRec() { 157 | preorderRec(this.root); 158 | } 159 | 160 | /** 161 | * A method that traverses the tree in postorder traversal using recursion and prints out all the nodes while traversing 162 | * by calling another helper, overloaded method with the same name. 163 | */ 164 | public void postorderRec() { 165 | postorderRec(this.root); 166 | } 167 | 168 | /** 169 | * A method that finds the k-th-smallest node of the current tree with the given root by calling another helper, 170 | * overloaded method with the same name by implementing inorder traversal. 171 | * 172 | * @param k The value of how small the node to be found is in the tree (e.g. 2nd-smallest or 5th-smallest) 173 | * @return The node that is found given the k value input, or may return null if no such node is found. 174 | */ 175 | public Node kthSmallest(int k) { 176 | // A Node variable that will be assigned and store the result of the helper function kthSmallestHelper2() 177 | Node kthSmallestNode = null; 178 | // A try-catch block to check if there is any exception thrown due to invalidity of input k 179 | try { 180 | kthSmallestNode = kthSmallestHelper2(this.root, k); 181 | // Simply return this variable as the result 182 | return kthSmallestNode; 183 | } 184 | // If an exception is caught, system should print a message saying that the entered k value is invalid 185 | catch (IllegalArgumentException e) { 186 | System.out.println("The entered k value is invalid! It is either smaller than 0 or greater than the number of nodes currently in the tree!"); 187 | // Return null because the given k value is invalid and henceforth no kth-smallest node can be found with it 188 | return null; 189 | } 190 | } 191 | 192 | // HELPER METHODS: // 193 | 194 | /** 195 | * A method that traverses and inserts a Node to a given Binary Search Tree with its root specified using recursion 196 | * 197 | * @param root The root of a B.S.T. in which a node will be added 198 | * @param key The key (data) of the node to be inserted 199 | */ 200 | private void insert(Node root, int key) { 201 | // A variable that stores the current node of the tree (i.e. current root of subtree) when traversing the tree 202 | Node traverseNode = root; 203 | // A variable that keeps track of the parent (previous) node of the current traversing node. 204 | Node parent = null; 205 | /* 206 | * The base case for recursion: the method should assign the current node of the tree that we are on the value 207 | * to be inserted, and then the method is stopped. This should only be done when the method has found the exact, 208 | * correct place in the tree to insert a node. 209 | */ 210 | if (traverseNode == null) { 211 | // Assigns the key to be inserted as a new leaf node of the tree by creating a new node with the given key: 212 | traverseNode = new Node(key); 213 | this.root = traverseNode; 214 | // Stops the function by using the return keyword 215 | return; 216 | } 217 | /* 218 | * A while-loop that stops when the traverse node is null. It will traverse the B.S.T. to find the place where 219 | * the new node should be inserted by continuously assigning the traversing node to be its child node in either its 220 | * right or left subtree, as described below: 221 | */ 222 | while (traverseNode != null) { 223 | // First, keeps track of the current parent of the traversing node: 224 | parent = traverseNode; 225 | // If the key to be inserted is smaller than the current traversing node's key, go to its left subtree 226 | if (key < traverseNode.key) { 227 | traverseNode = traverseNode.left; 228 | } 229 | // If the key to be inserted is greater than the current traversing node's key, go to its right subtree 230 | else if (key >= traverseNode.key) { 231 | traverseNode = traverseNode.right; 232 | } 233 | /* The loop will stop when the traversing node is null - i.e. it has reached the leaf of the tree where 234 | * the new node will be inserted. */ 235 | } 236 | /* 237 | * Now that we have found where to insert our new node, we will compare the given key with the key of our current 238 | * parent. If that key is greater than the current parent's key, create a new node and assign it as the left child node 239 | * of the current parent. 240 | */ 241 | if (key < parent.key) { 242 | parent.left = new Node(key); 243 | } 244 | /* 245 | * Otherwise, if the given key is greater than or equal to the current parent's key, assign the new node with 246 | * the given key to be the right child node of the current parent. 247 | */ 248 | else if (key >= parent.key) { 249 | parent.right = new Node(key); 250 | } 251 | } 252 | 253 | /** 254 | * A method that searches for a node with the specific key in the given B.S.T. with the given root using recursion 255 | * 256 | * @param root The root of the binary search tree that will be searched 257 | * @param key Any given key to be searched 258 | * @return The node is found to have the same key as the given input key. In the case that no node with such key is 259 | * found in the tree, the system will return the given root only, and prints out a confirmation that no such node with 260 | * given key is found in the tree. 261 | */ 262 | private Node search(Node root, int key) { 263 | // A variable that keeps track of the current node (i.e. current root of subtree) used when traversing the tree 264 | Node traverseNode = root; 265 | /* 266 | * Now, if the traverse node is null, which means that we have traversed the entire tree and found no matching 267 | * node. Thus, only the given root will be returned and a message will be printed to the screen to confirm that 268 | * no such key is found in the tree. 269 | */ 270 | if (traverseNode == null) { 271 | System.out.println("No Such Key or Element Exists in the Tree!"); 272 | return null; 273 | } 274 | /* 275 | * The base case for the recursion method: It should stop and return the node found if the node that has the same 276 | * key as the given key is found 277 | */ 278 | if (traverseNode.key == key) { 279 | return traverseNode; 280 | } 281 | /* 282 | * If the current traverse node's key is greater than the given key, traverse and search its left subtree as the 283 | * node to be found should now be in the traverse node's left subtree 284 | */ 285 | if (key < traverseNode.key) { 286 | traverseNode = search(traverseNode.left, key); 287 | } 288 | /* 289 | * Otherwise, if the current traverse node's key is smaller than or equal to the given key, traverse and search 290 | * its right subtree as the node to be found should now be in the traverse node's right subtree 291 | */ 292 | else if (key >= traverseNode.key) { 293 | traverseNode = search(traverseNode.right, key); 294 | } 295 | // At the end of the function, return the traversing node in order to stop the function and add a return statement 296 | return traverseNode; 297 | } 298 | 299 | /** 300 | * A method that will delete the node with the specific key in a B.S.T. and return te node that is deleted. 301 | * 302 | * @param root the root of the tree whose node is to be deleted 303 | * @param key the key of the node to be found and deleted 304 | * @return the node that is the new root of the new tree after deletion 305 | */ 306 | private Node delete(Node root, int key) { 307 | // A variable that stores and keeps track of the current traversing node (i.e. current root of subtree) while traversing the tree 308 | Node traverseNode = root; 309 | /* 310 | * In the base case of this method: return the current traversing node, as we have traversed the entire tree, 311 | * and we may or may not have found and deleted a node from the tree. This base case also works when the tree is empty, 312 | * as it will simply return the parsed-in root. 313 | */ 314 | if (traverseNode == null) { 315 | return null; 316 | } 317 | /* 318 | * If the current traversing node's key is greater than the given key, traverse its left subtree as the node to 319 | * be found and deleted is likely in this subtree, using recursion. 320 | */ 321 | if (traverseNode.key > key) { 322 | traverseNode.left = delete(traverseNode.left, key); 323 | } 324 | /* 325 | * If the current traversing node's key is smaller than the given key, traverse its right subtree as the node to 326 | * be found and deleted is likely in this subtree, using recursion. 327 | */ 328 | else if (traverseNode.key < key) { 329 | traverseNode.right = delete(traverseNode.right, key); 330 | } 331 | /* 332 | * If the current traversing node's key is the same as the given key, which means that we have found the node to 333 | * be deleted. We will now look at three different cases, as described below: 334 | */ 335 | else if (key == traverseNode.key) { 336 | /* 337 | * If the right child node of the current traversing node is null (which means that it has only 1 left child), 338 | * assign it to be its left child in order to delete it from the tree. 339 | */ 340 | if (traverseNode.right == null) { 341 | // A temporary Node variable to store the current node to be deleted, just in case it gets mixed up 342 | Node temporaryNode = traverseNode; 343 | // Assigns the current root (i.e. the current traversal node) to be its left child 344 | traverseNode = traverseNode.left; 345 | } 346 | /* 347 | * If the left child node of the current traversing node is null (which means that it has only 1 right child), 348 | * assign it to be its right child in order to delete it from the tree. 349 | */ 350 | else if (traverseNode.left == null) { 351 | // A temporary Node variable to store the current node to be deleted, just in case it gets mixed up 352 | Node temporaryNode = traverseNode; 353 | // Assigns the current root (i.e. the current traversal node) to be its right child 354 | traverseNode = traverseNode.right; 355 | } 356 | // Otherwise, if the node to be deleted is a leaf node (that has no children), simply delete it from the tree 357 | else if (traverseNode.left == null && traverseNode.right == null) { 358 | traverseNode = null; 359 | } 360 | /* 361 | * If the node to be deleted has two children, find the minimum key in its right subtree and replace its key 362 | * with the minimum key. Then traverse the current traversing node's right subtree to delete the minimum key 363 | * from the tree. 364 | */ 365 | else if (traverseNode.left != null && traverseNode.right != null) { 366 | // A temporary Node variable to store the current node to be deleted, just in case it gets mixed up with other variables 367 | Node temporaryNode = traverseNode; 368 | // A variable that stores the minimum key in the current traverse node's right subtree 369 | Node minimum = findMinimumInSubTree(temporaryNode.right); 370 | // Replace the current node's key to be the minimum node's key in order to delete it from the tree 371 | traverseNode.key = minimum.key; 372 | // Delete the minimum node's key from the tree in order to avoid any duplications in the tree 373 | traverseNode.right = delete(traverseNode.right, minimum.key); 374 | } 375 | } 376 | // Return the current traverse node in order to stop the function 377 | return traverseNode; 378 | } 379 | 380 | /** 381 | * A helper function that helps find the minimum node in the current tree or subtree given its root, using recursion 382 | * 383 | * @param root The node of the tree that will be searched 384 | * @return The minimum node in the current tree or subtree given its root 385 | */ 386 | private Node findMinimumInSubTree(Node root) { 387 | // A variable that stores and keeps track of the current traversing node (i.e. current root of subtree) while traversing the tree 388 | Node traverseNode = root; 389 | /* 390 | * The base case for the recursion: if the left child node of the current traversing node is null, return the 391 | * traversing node, as we have now found the smallest node in the current tree or subtree. 392 | */ 393 | if (traverseNode.left == null) { 394 | return traverseNode; 395 | } 396 | /* 397 | * Otherwise, traverse the current node's left subtree in order to find the smallest node in it. Then, return 398 | * the current traversing node in order to stop the function. 399 | */ 400 | else if (traverseNode.left != null) { 401 | traverseNode = findMinimumInSubTree(traverseNode.left); 402 | return traverseNode; 403 | } 404 | // Return the current traversal node 405 | return traverseNode; 406 | } 407 | 408 | /** 409 | * A method that traverses the tree in inorder traversal using recursion and prints out all the nodes while traversing 410 | * 411 | * @param root The root of the tree to be traversed 412 | */ 413 | private void inorderRec(Node root) { 414 | // A variable that stores and keeps track of the current traversing node (i.e. current root of subtree) while traversing the tree 415 | Node traverseNode = root; 416 | /* 417 | * The base case for the recursion: the function will stop when the traverse node is null, or when the tree 418 | * is empty or when the tree has been completely, fully traversed. 419 | */ 420 | if (traverseNode == null) { 421 | return; 422 | } 423 | // First, recursively traverse the left subtree of the current traversing node 424 | inorderRec(traverseNode.left); 425 | // Then, visit the current root & prints out the nodes as we traverse through the B.S.T.'s subtree 426 | System.out.print(traverseNode.key + " "); 427 | // Then, recursively traverse the right subtree of the current traversing node 428 | inorderRec(traverseNode.right); 429 | } 430 | 431 | /** 432 | * A method that traverses the tree in preorder traversal using recursion and prints out all the nodes while traversing 433 | * 434 | * @param root The root of the tree to be traversed 435 | */ 436 | public void preorderRec(Node root) { 437 | // A variable that stores and keeps track of the current traversing node (i.e. current root of subtree) while traversing the tree 438 | Node traverseNode = root; 439 | /* 440 | * The base case for the recursion: the function will stop when the traverse node is null, or when the tree 441 | * is empty or when the tree has been completely, fully traversed. 442 | */ 443 | if (traverseNode == null) { 444 | return; 445 | } 446 | // First, visit the current root & prints out the nodes of the tree as we traverse it 447 | System.out.print(traverseNode.key + " "); 448 | // Then, recursively traverse the left subtree of the current traversing node 449 | preorderRec(traverseNode.left); 450 | // Then, recursively traverse the right subtree of the current traversing node 451 | preorderRec(traverseNode.right); 452 | } 453 | 454 | /** 455 | * A method that traverses the tree in preorder traversal using recursion and prints out all the nodes while traversing 456 | * 457 | * @param root The root of the tree to be traversed 458 | */ 459 | private void postorderRec(Node root) { 460 | // A variable that stores and keeps track of the current traversing node (i.e. current root of subtree) while traversing the tree 461 | Node traverseNode = root; 462 | /* 463 | * The base case for the recursion: the function will stop when the traverse node is null, or when the tree 464 | * is empty or when the tree has been completely, fully traversed. 465 | */ 466 | if (traverseNode == null) { 467 | return; 468 | } 469 | // First, recursively traverse the left subtree of the current traversing node 470 | preorderRec(traverseNode.left); 471 | // Then, recursively traverse the right subtree of the current traversing node 472 | preorderRec(traverseNode.right); 473 | // Then, visit the current root & prints out the nodes of the tree as we traverse it 474 | System.out.print(traverseNode.key + " "); 475 | } 476 | 477 | /** 478 | * A method that helps find the k-th-smallest element/node in a given tree or subtree using recursion and inorder 479 | * traversal. 480 | * 481 | * @param root The root of the tree in which the k-th-smallest element will be found 482 | * @param k the value of how small the node to be found is in the tree (e.g. 2nd-smallest or 5th-smallest) 483 | * @return the k-th-smallest element 484 | */ 485 | private Node kthSmallestHelper1(Node root, int k) { 486 | // A variable that stores and keeps track of the current traversing node (i.e. current root of subtree) while traversing the tree 487 | Node traverseNode = root; 488 | // A node that keeps track of the k-th-smallest node 489 | Node kthSmallestNode = null; 490 | /* 491 | * Base case for the recursion: If the current traverse node is null, meaning that either we have traversed the 492 | * entire tree or when the tree is null 493 | */ 494 | if (traverseNode == null) { 495 | return traverseNode; 496 | } 497 | // First, traverse the left subtree of the current node to perform inorder traversal 498 | kthSmallestNode = kthSmallestHelper1(traverseNode.left, k); 499 | /* 500 | * Whenever the k-th-smallest node variable is assigned a value (i.e. it is found), the method should stop and 501 | * return this variable. 502 | */ 503 | if (kthSmallestNode != null) { 504 | return kthSmallestNode; 505 | } 506 | // Otherwise, increment the current number of nodes visited while traversing the tree by 1 507 | numNodesVisited = numNodesVisited + 1; 508 | /* 509 | * Check if the current number of nodes visited field is equal to the given k-value. If it is, return the current 510 | * traversing node. Otherwise, let the method continue as normal. 511 | */ 512 | if (numNodesVisited == k) { 513 | // Assign the kth-smallest-node variable to be the current traversing node and return it 514 | kthSmallestNode = traverseNode; 515 | return kthSmallestNode; 516 | } 517 | /* 518 | * After completing traversing the current root's left subtree, we will now traverse its right subtree to complete 519 | * the inorder traversal of the tree. 520 | */ 521 | kthSmallestNode = kthSmallestHelper1(traverseNode.right, k); 522 | // Now, at the end of the method, return the current kth-smallest-node in order to stop the function. 523 | return kthSmallestNode; 524 | } 525 | 526 | /** 527 | * A method that finds the k-th-smallest node of the current tree with the given root 528 | * 529 | * @param root the root of the tree to find the node from 530 | * @param k The value of how small the node to be found is in the tree (e.g. 2nd-smallest or 5th-smallest) 531 | * @return the k-th-smallest node of the current tree 532 | * @throws IllegalArgumentException Throw this exception if the entered k value is invalid (i.e. it is greater than 533 | * the current number of nodes in the tree or is below 0.) 534 | */ 535 | private Node kthSmallestHelper2(Node root, int k) { 536 | /* Throw this exception if the entered k value is invalid (i.e. it is greater than the current number of nodes 537 | * in the tree or is below 0.) */ 538 | if (k < 0 || k > numNodes(this.root)) { 539 | throw new IllegalArgumentException(); 540 | } 541 | // Resets the field that keeps track of the number of nodes visited when traversing the tree to 0 542 | numNodesVisited = 0; 543 | /* 544 | * Calls the helper function that will traverse the tree and find the k-th-smallest node. 545 | * Two separate functions are written to achieve this task to avoid the reuse of the above-mentioned field when 546 | * using this method multiple times in a row, as the reuse of this field can lead to inaccurate results. 547 | */ 548 | return kthSmallestHelper1(root, k); 549 | } 550 | 551 | /** 552 | * A function that traverses and calculates the total number of nodes currently in the tree using recursion. 553 | * 554 | * @param root The root of the tree whose nodes are being counted 555 | * @return Total number of nodes currently in the B.S.T. 556 | */ 557 | private int numNodes(Node root){ 558 | // Base Case: If a null node is reached or a given tree is empty 559 | if (root == null) { 560 | return 0; 561 | } 562 | // Recursively traverse left & right subtree of current root node to visit all nodes currently in tree 563 | return 1 + numNodes(root.left) + numNodes(root.right); 564 | } 565 | 566 | } -------------------------------------------------------------------------------- /Main.java: -------------------------------------------------------------------------------- 1 | /** 2 | * A class that tests the behavior of the methods in the Binary Search Tree class 3 | * @author David Nguyen 4 | * @since 03/08/2023 5 | */ 6 | public class Main { 7 | 8 | /** 9 | * A method that tests and demonstrates the behavior of the methods in the Binary Search Tree class. 10 | * 11 | * @param args any specified arguments to run the main method. 12 | */ 13 | public static void main(String[] args) { 14 | // Creating a new tree and inserting nodes into the tree 15 | BinarySearchTree tree = new BinarySearchTree(); 16 | tree.insert(40); 17 | tree.insert(20); 18 | tree.insert(10); 19 | tree.insert(30); 20 | tree.insert(60); 21 | tree.insert(50); 22 | tree.insert(70); 23 | tree.insert(5); 24 | tree.insert(15); 25 | tree.insert(55); 26 | tree.insert(75); 27 | tree.insert(95); 28 | // Now print out the tree to show its current state in three different types of tree traversals 29 | System.out.println("1) Create & Print Out The Following Binary Search Tree: "); 30 | System.out.println("Inorder Traversal: "); 31 | tree.inorderRec(); 32 | System.out.println(); 33 | System.out.println("Preorder Traversal: "); 34 | tree.preorderRec(); 35 | System.out.println(); 36 | System.out.println("Postorder Traversal: "); 37 | tree.postorderRec(); 38 | System.out.println(); 39 | System.out.println("==> The tree constructor and the insert method both worked as expected!"); 40 | System.out.println("==> The three traversal methods (Inorder, Postorder, and Preorder) also worked as expected!"); 41 | // Now test the behavior of delete() method, with the first case of deleting a node with two children 42 | System.out.println("2) Deleting node 40 which have two children and is also the root node: "); 43 | Node newRoot = tree.delete(40); 44 | System.out.println("Inorder Traversal After Deletion: "); 45 | tree.inorderRec(); 46 | System.out.println(); 47 | System.out.println("Preorder Traversal After Deletion: "); 48 | tree.preorderRec(); 49 | System.out.println(); 50 | System.out.println("Postorder Traversal After Deletion: "); 51 | tree.postorderRec(); 52 | System.out.println(); 53 | System.out.println("The value of the new root node is: "); 54 | System.out.println(newRoot.key); 55 | // Now test the behavior of delete() method, with the second case of deleting a node with one child 56 | System.out.println("3) Deleting node 70 which have one child: "); 57 | Node newRoot1 = tree.delete(70); 58 | // Print out the entire tree to show its current state after deletion: 59 | System.out.println("Inorder Traversal After Deletion: "); 60 | tree.inorderRec(); 61 | System.out.println(); 62 | System.out.println("Preorder Traversal After Deletion: "); 63 | tree.preorderRec(); 64 | System.out.println(); 65 | System.out.println("Postorder Traversal After Deletion: "); 66 | tree.postorderRec(); 67 | System.out.println(); 68 | System.out.println("The value of the new root node is: "); 69 | System.out.println(newRoot1.key); 70 | // Now test the behavior of delete() method, with the third case of deleting a node with no children 71 | System.out.println("4) Deleting node 55 which have no children - is a leaf node: "); 72 | Node newRoot2 = tree.delete(55); 73 | // Print out the entire tree to show its current state after deletion: 74 | System.out.println("Inorder Traversal After Deletion: "); 75 | tree.inorderRec(); 76 | System.out.println(); 77 | System.out.println("Preorder Traversal After Deletion: "); 78 | tree.preorderRec(); 79 | System.out.println(); 80 | System.out.println("Postorder Traversal After Deletion: "); 81 | tree.postorderRec(); 82 | System.out.println(); 83 | System.out.println("The value of the new root node is: "); 84 | System.out.println(newRoot2.key); 85 | // Now find the node with the key of 20 in the tree and print the result out 86 | System.out.println("5) Now Find The Node That Has The Key Of 5: "); 87 | boolean found = tree.search(5); 88 | System.out.println(found); 89 | // Now find the node with the key of 30 in the tree and print the result out 90 | System.out.println("6) Now Find The Node That Has The Key Of 30: "); 91 | boolean found1 = tree.search(30); 92 | System.out.println(found1); 93 | // Now find the node with the key of 60 in the tree and print the result out 94 | System.out.println("7) Now Find The Node That Has The Key Of 60: "); 95 | boolean found3 = tree.search(60); 96 | System.out.println(found3); 97 | // Now find the node with the key of 95 in the tree and print the result out 98 | System.out.println("7) Now Find The Node That Has The Key Of 95: "); 99 | boolean found4 = tree.search(95); 100 | System.out.println(found4); 101 | // Now find the node with the key of 100 in the tree and print the result out 102 | System.out.println("8) Now Find The Node That Has The Key Of 100 - Which Is Not In The Tree: "); 103 | boolean found2 = tree.search(100); 104 | System.out.println(found2); 105 | System.out.println("=> The system should say that no such node with the given key in the tree and print false."); 106 | // Now find the 2nd smallest element in the current tree (after deletions), which should be 10 107 | System.out.println("9) Now Find The 2nd Smallest Element In The Tree: "); 108 | Node smallest = tree.kthSmallest(2); 109 | System.out.println(smallest.key); 110 | System.out.println("==> System Should Print 10 Because It's The 2nd Smallest!"); 111 | // Now find the 5th smallest element in the current tree (after deletions), which should be 30 112 | System.out.println("10) Now Find The 5th Smallest Element In The Tree: "); 113 | Node smallest1 = tree.kthSmallest(5); 114 | System.out.println(smallest1); 115 | System.out.println(smallest1.key); 116 | System.out.println("==> System Should Print Out The Node And The Value 30 Because It's The 5th Smallest!"); 117 | // Now find the 7th smallest element in the current tree (after deletions), which should be 60 118 | System.out.println("11) Now Find The 7th Smallest Element In The Tree: "); 119 | Node smallest2 = tree.kthSmallest(7); 120 | System.out.println(smallest2); 121 | System.out.println(smallest2.key); 122 | System.out.println("==> System Should Print Out The Node And The Value 60 Because It's The 7th Smallest!"); 123 | // Now find the smallest element in the current tree (after deletions), which should be 60 124 | System.out.println("12) Now Find The SMALLEST Element In The Tree: "); 125 | Node smallest3 = tree.kthSmallest(1); 126 | System.out.println(smallest3); 127 | System.out.println(smallest3.key); 128 | System.out.println("==> System Should Print Out The Node And The Value 5 Because It's The Smallest!"); 129 | // Now find the largest element in the current tree (after deletions), which should be 95 130 | System.out.println("14) Now Find The LARGEST Element In The Tree: "); 131 | Node smallest4 = tree.kthSmallest(9); 132 | System.out.println(smallest4.key); 133 | System.out.println("==> System Should Print Out The Node And The Value 95 Because It's The Largest!"); 134 | System.out.println("15) Test If The Entered K Value Is Invalid - Greater Than Number of Nodes in Tree:"); 135 | System.out.println(tree.kthSmallest(100)); 136 | System.out.println("16) Test If The Entered K Value Is Invalid - Smaller Than 0:"); 137 | System.out.println(tree.kthSmallest(-1)); 138 | System.out.println(tree.kthSmallest(-100)); 139 | System.out.println("==> System Should Print A Message Noticing The User That Enter K Value Is Invalid & Return A Null Value."); 140 | // Now try converting an array of single digits (with duplicates) into a tree 141 | System.out.println("17) Try Converting An Array of Single Digits Into A Tree - The Existing Tree Should Be Overwritten:"); 142 | System.out.println("The Array To Be Parsed In Is:"); 143 | int[] values = {1,3,2,4,7,8,9,6,9,9}; 144 | // Prints the values in the parsed-in array out to the screen 145 | for (int value : values) { 146 | System.out.print(value + " "); 147 | } 148 | // The method createTree() will also print out the tree in three different traversals to show the current state of the tree 149 | System.out.println(); 150 | tree.createTree(values); 151 | System.out.println(); 152 | // Now try converting an array of multiple digits (with duplicates) into a tree 153 | System.out.println("18) Try Converting An Array of Multiple Digits Into A Tree - The Existing Tree Should Be Overwritten:"); 154 | System.out.println("The Array To Be Parsed In Is:"); 155 | int[] values2 = {12,33,22,45,75,8,98,56,9,99,1230,9999,10450}; 156 | // Prints the values in the parsed-in array out to the screen 157 | for (int value : values2) { 158 | System.out.print(value + " "); 159 | } 160 | // The method createTree() will also print out the tree in three different traversals to show the current state of the tree 161 | System.out.println(); 162 | tree.createTree(values2); 163 | System.out.println(); 164 | System.out.println("==> The createTree() method works perfectly!"); 165 | System.out.println("===> Now that all other methods have been tested, test the other constructors of the Binary Search Tree class"); 166 | // Now that all other methods have been tested, test the other constructors of the Binary Search Tree class: 167 | // Creating a new tree and inserting nodes into the tree using the second constructor, which takes in an int 168 | BinarySearchTree tree2 = new BinarySearchTree(40); 169 | tree2.insert(20); 170 | tree2.insert(10); 171 | tree2.insert(30); 172 | tree2.insert(60); 173 | tree2.insert(50); 174 | tree2.insert(70); 175 | tree2.insert(5); 176 | tree2.insert(15); 177 | tree2.insert(55); 178 | tree2.insert(75); 179 | tree2.insert(95); 180 | // Now print out the tree to show its current state in three different types of tree traversals 181 | System.out.println("19) Create & Print Out The Following Binary Search Tree Using The Second Constructor: "); 182 | System.out.println("Inorder Traversal: "); 183 | tree2.inorderRec(); 184 | System.out.println(); 185 | System.out.println("Preorder Traversal: "); 186 | tree2.preorderRec(); 187 | System.out.println(); 188 | System.out.println("Postorder Traversal: "); 189 | tree2.postorderRec(); 190 | System.out.println(); 191 | System.out.println("=> The second constructor and the insert method both worked as expected!"); 192 | // Creating a new tree and inserting nodes into the tree using the third constructor, which takes in a node 193 | Node rootNode = new Node(40); 194 | BinarySearchTree tree1 = new BinarySearchTree(rootNode); 195 | tree1.insert(20); 196 | tree1.insert(10); 197 | tree1.insert(30); 198 | tree1.insert(60); 199 | tree1.insert(50); 200 | tree1.insert(70); 201 | tree1.insert(5); 202 | tree1.insert(15); 203 | tree1.insert(55); 204 | tree1.insert(75); 205 | tree1.insert(95); 206 | // Now print out the tree to show its current state in three different types of tree traversals 207 | System.out.println("20) Create & Print Out The Following Binary Search Tree Using The Third Constructor: "); 208 | System.out.println("Inorder Traversal: "); 209 | tree1.inorderRec(); 210 | System.out.println(); 211 | System.out.println("Preorder Traversal: "); 212 | tree1.preorderRec(); 213 | System.out.println(); 214 | System.out.println("Postorder Traversal: "); 215 | tree1.postorderRec(); 216 | System.out.println(); 217 | System.out.println("=> The third constructor and the insert method both worked as expected!"); 218 | /* Now all methods of a 'normal' tree have been tested, we will now test the performance of the methods when the 219 | * tree is null (i.e. empty). Test especially for Null Pointer Exceptions */ 220 | System.out.println("21) Testing Search Method If Tree Is Empty: "); 221 | BinarySearchTree tree4 = new BinarySearchTree(); 222 | System.out.println(tree4.search(5)); 223 | System.out.println("=> The program should print 'false' because the tree is currently empty."); 224 | System.out.println("22) Testing Delete Method If Tree Is Empty"); 225 | System.out.println(tree4.delete(5)); 226 | System.out.println("23) Testing Three Traversal Methods If Tree Is Empty:"); 227 | System.out.println("Inorder Traversal:"); 228 | tree4.inorderRec(); 229 | System.out.println(); 230 | System.out.println("Preorder Traversal:"); 231 | tree4.preorderRec(); 232 | System.out.println(); 233 | System.out.println("Postorder Traversal: "); 234 | tree4.postorderRec(); 235 | System.out.println(); 236 | System.out.println("=> Nothing should be printed out because the tree is currently empty!"); 237 | System.out.println("24) Testing The Find Kth-Smallest Method If Tree Is Empty. Case 1: Test if K is positive:"); 238 | System.out.println(tree4.kthSmallest(2)); 239 | System.out.println("25) Testing The Find Kth-Smallest Method If Tree Is Empty. Case 2: Test if K is negative:"); 240 | System.out.println(tree4.kthSmallest(-99)); 241 | int[] valueEmpty = new int[6]; 242 | System.out.println("26) Now try creating a B.S.T. from an empty array"); 243 | for (int value : valueEmpty) { 244 | System.out.println(value); 245 | } 246 | tree4.createTree(valueEmpty); 247 | System.out.println(); 248 | System.out.println("=> A tree was successfully created from the given empty array of int!"); 249 | // Now we will test the case where the B.S.T. has only one node in it. Still watch out for null pointer exceptions 250 | BinarySearchTree tree6 = new BinarySearchTree(); 251 | tree6.insert(9999999); 252 | System.out.println("27) Testing Search Method If Tree Has Only One Node: "); 253 | System.out.println(tree6.search(5)); 254 | System.out.println("28) Testing Delete Method If Tree Has Only One Node"); 255 | Node delete6 = tree6.delete(5); 256 | System.out.println(delete6); 257 | System.out.println(delete6.key); 258 | System.out.println("29) Testing Three Traversal Methods Has Only One Node:"); 259 | System.out.println("Inorder Traversal:"); 260 | tree6.inorderRec(); 261 | System.out.println(); 262 | System.out.println("Preorder Traversal:"); 263 | tree6.preorderRec(); 264 | System.out.println(); 265 | System.out.println("Postorder Traversal: "); 266 | tree6.postorderRec(); 267 | System.out.println(); 268 | System.out.println("=> Only one node should be printed out because the tree has only one node!"); 269 | System.out.println("30) Testing The Find Kth-Smallest Method If Tree Has Only One Node. Case 1: Test if K is valid:"); 270 | Node kthSmallest2 = tree6.kthSmallest(1); 271 | System.out.println(kthSmallest2); 272 | System.out.println(kthSmallest2.key); 273 | System.out.println("=> System Should Print Out The Node And The Value 9999999"); 274 | System.out.println("31) Testing The Find Kth-Smallest Method If Tree Has Only One Node. Case 2: Test if K is invalid - NEGATIVE K:"); 275 | System.out.println(tree6.kthSmallest(-999)); 276 | System.out.println("32) Testing The Find Kth-Smallest Method If Tree Has Only One Node. Case 3: Test if K is invalid - TOO LARGE K:"); 277 | System.out.println(tree6.kthSmallest(2)); 278 | System.out.println(); 279 | System.out.println("===> If this statement is reached, all methods have worked correctly and performed as expected!"); 280 | } 281 | 282 | } -------------------------------------------------------------------------------- /Node.java: -------------------------------------------------------------------------------- 1 | /** 2 | * A class that represents a Node in the Binary Search Tree, which has its key (data), its left and right child pointers. 3 | * It is declared to be available for any classes in the package to use only, so it does not have any access modifiers. 4 | * @author David Nguyen 5 | * @since 03/08/2023 6 | */ 7 | class Node { 8 | 9 | // A field that represents the key (data) of the node 10 | protected int key; 11 | 12 | // A field that stores the left child pointer of the node (points to the left child of the node) 13 | protected Node left; 14 | 15 | // A field that stores the right child pointer of the node (points to the right child of the node) 16 | protected Node right; 17 | 18 | /** 19 | * A constructor that creates a node instance that takes in a key (data) as an integer. 20 | * When a node is created, its left and right pointer should initially be null. Additionally, the key of the node 21 | * should also be assigned the parsed-in key value 22 | * @param key The key (data) of the node to be created 23 | */ 24 | protected Node(int key) { 25 | this.key = key; 26 | this.left = null; 27 | this.right = null; 28 | } 29 | 30 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Binary Search Tree - DSA Project 2 | 3 | ## Overview 4 | This Java project implements a Binary Search Tree (BST) with fundamental operations such as insertion, deletion, and traversal. Designed with efficiency and simplicity in mind, this class provides an intuitive way to manage and manipulate a collection of integers in a hierarchical structure. 5 | 6 | ## Features 7 | - **Dynamic Tree Construction**: Create a BST either empty, with a single root node, or by parsing an array of integers. 8 | - **Insertion**: Add new elements to the tree while maintaining the BST properties. 9 | - **Deletion**: Remove elements from the tree, adjusting the structure as necessary to preserve BST properties. 10 | - **Search**: Check whether a specific value exists within the tree. 11 | - **Traversal**: Inorder, preorder, and postorder traversal methods to explore the tree's contents. 12 | - **K-th Smallest Element**: Retrieve the k-th smallest element from the tree, demonstrating an application of inorder traversal. 13 | - **Create Tree from Array**: Build a new BST from an array of integers, replacing any existing tree. 14 | 15 | ## Prerequisites 16 | - Java Development Kit (JDK) 11 or later. 17 | - A Java IDE (e.g. IntelliJ IDEA or Eclipse) is highly recommended. 18 | 19 | ## Setup and Compilation 20 | 1. Ensure Java is installed on your system. You can verify this by running `java -version` in your command line or terminal. 21 | 2. Clone or download this repository to your local machine. 22 | 3. Navigate to the directory containing the `BinarySearchTree.java` file. 23 | 4. Compile the class using the Java compiler: 24 | ```bash 25 | javac BinarySearchTree.java 26 | ``` 27 | 28 | ## Usage 29 | ### Creating a BST 30 | Instantiate a BST object in your Java program. You can create a tree in three ways: 31 | - Empty tree: `BinarySearchTree bst = new BinarySearchTree();` 32 | - Tree with an integer root: `BinarySearchTree bst = new BinarySearchTree(10);` 33 | - Tree with a Node as root: `BinarySearchTree bst = new BinarySearchTree(new Node(10));` 34 | 35 | ### Inserting Elements 36 | Add elements to your BST: 37 | ```java 38 | bst.insert(5); 39 | bst.insert(15); 40 | ``` 41 | 42 | ### Deleting Elements 43 | Remove elements by value: 44 | ```java 45 | bst.delete(5); 46 | ``` 47 | 48 | ### Searching for Elements 49 | Check if an element exists in the tree: 50 | ```java 51 | boolean found = bst.search(15); 52 | ``` 53 | 54 | ### Traversing the Tree 55 | Perform different tree traversals: 56 | ```java 57 | bst.inorderRec(); 58 | bst.preorderRec(); 59 | bst.postorderRec(); 60 | ``` 61 | 62 | ### Finding the K-th Smallest Element 63 | Retrieve the k-th smallest element from the BST: 64 | ```java 65 | Node kthSmallest = bst.kthSmallest(3); 66 | if (kthSmallest != null) { 67 | System.out.println("K-th Smallest: " + kthSmallest.key); 68 | } 69 | ``` 70 | 71 | ### Creating a Tree from an Array 72 | Overwrite the current tree with a new tree constructed from an array of integers: 73 | ```java 74 | int[] values = {3, 1, 4, 2}; 75 | bst.createTree(values); 76 | ``` 77 | 78 | ### Main File 79 | There is also a Main.java file, which comprehensively tests all the functions and methods of the BST class. Feel free to run it as follows: 80 | ```bash 81 | java Main 82 | ``` 83 | 84 | ## Contributing 85 | Contributions to improve the Binary Search Tree implementation or extend its functionality are welcome. Please fork the repository, make your changes, and submit a pull request with a clear description of your modifications or additions. 86 | 87 | --- 88 | 89 | Created with ❤️ by [Son Nguyen](https://github.com/hoangsonww) in 2023. 90 | -------------------------------------------------------------------------------- /out/production/Binary-Search-Tree-DSA/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /out/production/Binary-Search-Tree-DSA/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /out/production/Binary-Search-Tree-DSA/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /out/production/Binary-Search-Tree-DSA/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /out/production/Binary-Search-Tree-DSA/Binary-Search-Tree-DSA.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /out/production/Binary-Search-Tree-DSA/BinarySearchTree.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hoangsonww/Binary-Search-Tree-DSA/256713db8679d5d58abc9da3333b853969baf3a1/out/production/Binary-Search-Tree-DSA/BinarySearchTree.class -------------------------------------------------------------------------------- /out/production/Binary-Search-Tree-DSA/Main.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hoangsonww/Binary-Search-Tree-DSA/256713db8679d5d58abc9da3333b853969baf3a1/out/production/Binary-Search-Tree-DSA/Main.class -------------------------------------------------------------------------------- /out/production/Binary-Search-Tree-DSA/Node.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hoangsonww/Binary-Search-Tree-DSA/256713db8679d5d58abc9da3333b853969baf3a1/out/production/Binary-Search-Tree-DSA/Node.class -------------------------------------------------------------------------------- /out/production/Binary-Search-Tree-DSA/README.md: -------------------------------------------------------------------------------- 1 | # Binary Search Tree - DSA Project 2 | 3 | ## Overview 4 | This Java project implements a Binary Search Tree (BST) with fundamental operations such as insertion, deletion, and traversal. Designed with efficiency and simplicity in mind, this class provides an intuitive way to manage and manipulate a collection of integers in a hierarchical structure. 5 | 6 | ## Features 7 | - **Dynamic Tree Construction**: Create a BST either empty, with a single root node, or by parsing an array of integers. 8 | - **Insertion**: Add new elements to the tree while maintaining the BST properties. 9 | - **Deletion**: Remove elements from the tree, adjusting the structure as necessary to preserve BST properties. 10 | - **Search**: Check whether a specific value exists within the tree. 11 | - **Traversal**: Inorder, preorder, and postorder traversal methods to explore the tree's contents. 12 | - **K-th Smallest Element**: Retrieve the k-th smallest element from the tree, demonstrating an application of inorder traversal. 13 | - **Create Tree from Array**: Build a new BST from an array of integers, replacing any existing tree. 14 | 15 | ## Prerequisites 16 | - Java Development Kit (JDK) 11 or later. 17 | 18 | ## Setup and Compilation 19 | 1. Ensure Java is installed on your system. You can verify this by running `java -version` in your command line or terminal. 20 | 2. Clone or download this repository to your local machine. 21 | 3. Navigate to the directory containing the `BinarySearchTree.java` file. 22 | 4. Compile the class using the Java compiler: 23 | ```bash 24 | javac BinarySearchTree.java 25 | ``` 26 | 27 | ## Usage 28 | ### Creating a BST 29 | Instantiate a BST object in your Java program. You can create a tree in three ways: 30 | - Empty tree: `BinarySearchTree bst = new BinarySearchTree();` 31 | - Tree with an integer root: `BinarySearchTree bst = new BinarySearchTree(10);` 32 | - Tree with a Node as root: `BinarySearchTree bst = new BinarySearchTree(new Node(10));` 33 | 34 | ### Inserting Elements 35 | Add elements to your BST: 36 | ```java 37 | bst.insert(5); 38 | bst.insert(15); 39 | ``` 40 | 41 | ### Deleting Elements 42 | Remove elements by value: 43 | ```java 44 | bst.delete(5); 45 | ``` 46 | 47 | ### Searching for Elements 48 | Check if an element exists in the tree: 49 | ```java 50 | boolean found = bst.search(15); 51 | ``` 52 | 53 | ### Traversing the Tree 54 | Perform different tree traversals: 55 | ```java 56 | bst.inorderRec(); 57 | bst.preorderRec(); 58 | bst.postorderRec(); 59 | ``` 60 | 61 | ### Finding the K-th Smallest Element 62 | Retrieve the k-th smallest element from the BST: 63 | ```java 64 | Node kthSmallest = bst.kthSmallest(3); 65 | if (kthSmallest != null) { 66 | System.out.println("K-th Smallest: " + kthSmallest.key); 67 | } 68 | ``` 69 | 70 | ### Creating a Tree from an Array 71 | Overwrite the current tree with a new tree constructed from an array of integers: 72 | ```java 73 | int[] values = {3, 1, 4, 2}; 74 | bst.createTree(values); 75 | ``` 76 | 77 | ### Main File 78 | There is also a Main.java file, which comprehensively tests all the functions and methods of the BST class. Feel free to run it as follows: 79 | ```bash 80 | java Main 81 | ``` 82 | 83 | ## Contributing 84 | Contributions to improve the Binary Search Tree implementation or extend its functionality are welcome. Please fork the repository, make your changes, and submit a pull request with a clear description of your modifications or additions. 85 | 86 | --- 87 | --------------------------------------------------------------------------------