|
| 1 | +/** |
| 2 | + * |
| 3 | + * |
| 4 | + * <h1>Binary Search Tree (Iterative)</h1> |
| 5 | + * |
| 6 | + * <p>An implementation of BST iteratively. Binary Search Tree is a binary tree which satisfies |
| 7 | + * three properties: left child is less than root node, right child is grater than root node, both |
| 8 | + * left and right childs must themselves be a BST. |
| 9 | + * |
| 10 | + * @author [Lakhan Nad](https://github.com/Lakhan-Nad) |
| 11 | + */ |
| 12 | +import java.util.Stack; |
| 13 | + |
| 14 | +public class BSTIterative { |
| 15 | + /** Reference for the node of BST. */ |
| 16 | + private Node root; |
| 17 | + |
| 18 | + /** Default Constructor Initializes the root of BST with null. */ |
| 19 | + BSTIterative() { |
| 20 | + root = null; |
| 21 | + } |
| 22 | + |
| 23 | + /** main function for tests */ |
| 24 | + public static void main(String[] args) { |
| 25 | + BSTIterative tree = new BSTIterative(); |
| 26 | + tree.add(3); |
| 27 | + tree.add(2); |
| 28 | + tree.add(9); |
| 29 | + assert !tree.find(4) : "4 is not yet present in BST"; |
| 30 | + assert tree.find(2) : "2 should be present in BST"; |
| 31 | + tree.remove(2); |
| 32 | + assert !tree.find(2) : "2 was just deleted from BST"; |
| 33 | + tree.remove(1); |
| 34 | + assert !tree.find(1) : "Since 1 was not present so find deleting would do no change"; |
| 35 | + tree.add(30); |
| 36 | + tree.add(40); |
| 37 | + assert tree.find(40) : "40 was inserted but not found"; |
| 38 | + /* |
| 39 | + Will print following order |
| 40 | + 3 9 30 40 |
| 41 | + */ |
| 42 | + tree.inorder(); |
| 43 | + } |
| 44 | + |
| 45 | + /** |
| 46 | + * A method to insert a new value in BST. If the given value is already present in BST the |
| 47 | + * insertion is ignored. |
| 48 | + * |
| 49 | + * @param data the value to be inserted |
| 50 | + */ |
| 51 | + public void add(int data) { |
| 52 | + Node parent = null; |
| 53 | + Node temp = this.root; |
| 54 | + int rightOrLeft = -1; |
| 55 | + /* Finds the proper place this node can |
| 56 | + * be placed in according to rules of BST. |
| 57 | + */ |
| 58 | + while (temp != null) { |
| 59 | + if (temp.data > data) { |
| 60 | + parent = temp; |
| 61 | + temp = parent.left; |
| 62 | + rightOrLeft = 0; |
| 63 | + } else if (temp.data < data) { |
| 64 | + parent = temp; |
| 65 | + temp = parent.right; |
| 66 | + rightOrLeft = 1; |
| 67 | + } else { |
| 68 | + System.out.println(data + " is already present in BST."); |
| 69 | + return; // if data already present we ignore insertion |
| 70 | + } |
| 71 | + } |
| 72 | + /* Creates a newNode with the value passed |
| 73 | + * Since this data doesn't already exists |
| 74 | + */ |
| 75 | + Node newNode = new Node(data); |
| 76 | + /* If the parent node is null |
| 77 | + * then the insertion is to be done in |
| 78 | + * root itself. |
| 79 | + */ |
| 80 | + if (parent == null) { |
| 81 | + this.root = newNode; |
| 82 | + } else { |
| 83 | + /* Check if insertion is to be made in |
| 84 | + * left or right subtree. |
| 85 | + */ |
| 86 | + if (rightOrLeft == 0) { |
| 87 | + parent.left = newNode; |
| 88 | + } else { |
| 89 | + parent.right = newNode; |
| 90 | + } |
| 91 | + } |
| 92 | + } |
| 93 | + |
| 94 | + /** |
| 95 | + * A method to delete the node in BST. If node is present it will be deleted |
| 96 | + * |
| 97 | + * @param data the value that needs to be deleted |
| 98 | + */ |
| 99 | + public void remove(int data) { |
| 100 | + Node parent = null; |
| 101 | + Node temp = this.root; |
| 102 | + int rightOrLeft = -1; |
| 103 | + /* Find the parent of the node and node itself |
| 104 | + * That is to be deleted. |
| 105 | + * parent variable store parent |
| 106 | + * temp stores node itself. |
| 107 | + * rightOrLeft use to keep track weather child |
| 108 | + * is left or right subtree |
| 109 | + */ |
| 110 | + while (temp != null) { |
| 111 | + if (temp.data == data) { |
| 112 | + break; |
| 113 | + } else if (temp.data > data) { |
| 114 | + parent = temp; |
| 115 | + temp = parent.left; |
| 116 | + rightOrLeft = 0; |
| 117 | + } else { |
| 118 | + parent = temp; |
| 119 | + temp = parent.right; |
| 120 | + rightOrLeft = 1; |
| 121 | + } |
| 122 | + } |
| 123 | + /* If temp is null than node with given value is not |
| 124 | + * present in our tree. |
| 125 | + */ |
| 126 | + if (temp != null) { |
| 127 | + Node replacement; // used to store the new values for replacing nodes |
| 128 | + if (temp.right == null && temp.left == null) { // Leaf node Case |
| 129 | + replacement = null; |
| 130 | + } else if (temp.right == null) { // Node with only right child |
| 131 | + replacement = temp.left; |
| 132 | + temp.left = null; |
| 133 | + } else if (temp.left == null) { // Node with only left child |
| 134 | + replacement = temp.right; |
| 135 | + temp.right = null; |
| 136 | + } else { |
| 137 | + /* If both left and right child are present |
| 138 | + * we replace this nodes data with |
| 139 | + * leftmost node's data in its right subtree |
| 140 | + * to maintain the balance of BST. |
| 141 | + * And then delete that node |
| 142 | + */ |
| 143 | + if (temp.right.left == null) { |
| 144 | + temp.data = temp.right.data; |
| 145 | + replacement = temp; |
| 146 | + temp.right = temp.right.right; |
| 147 | + } else { |
| 148 | + Node parent2 = temp.right; |
| 149 | + Node child = temp.right.left; |
| 150 | + while (child.left != null) { |
| 151 | + parent2 = child; |
| 152 | + child = parent2.left; |
| 153 | + } |
| 154 | + temp.data = child.data; |
| 155 | + parent2.left = child.right; |
| 156 | + replacement = temp; |
| 157 | + } |
| 158 | + } |
| 159 | + /* Change references of parent after |
| 160 | + * deleting the child. |
| 161 | + */ |
| 162 | + if (parent == null) { |
| 163 | + this.root = replacement; |
| 164 | + } else { |
| 165 | + if (rightOrLeft == 0) { |
| 166 | + parent.left = replacement; |
| 167 | + } else { |
| 168 | + parent.right = replacement; |
| 169 | + } |
| 170 | + } |
| 171 | + } |
| 172 | + } |
| 173 | + |
| 174 | + /** A method for inorder traversal of BST. */ |
| 175 | + public void inorder() { |
| 176 | + if (this.root == null) { |
| 177 | + System.out.println("This BST is empty."); |
| 178 | + return; |
| 179 | + } |
| 180 | + System.out.println("Inorder traversal of this tree is:"); |
| 181 | + Stack<Node> st = new Stack<Node>(); |
| 182 | + Node cur = this.root; |
| 183 | + while (cur != null || !st.empty()) { |
| 184 | + while (cur != null) { |
| 185 | + st.push(cur); |
| 186 | + cur = cur.left; |
| 187 | + } |
| 188 | + cur = st.pop(); |
| 189 | + System.out.print(cur.data + " "); |
| 190 | + cur = cur.right; |
| 191 | + } |
| 192 | + System.out.println(); // for next line |
| 193 | + } |
| 194 | + |
| 195 | + /** A method used to print postorder traversal of BST. */ |
| 196 | + public void postorder() { |
| 197 | + if (this.root == null) { |
| 198 | + System.out.println("This BST is empty."); |
| 199 | + return; |
| 200 | + } |
| 201 | + System.out.println("Postorder traversal of this tree is:"); |
| 202 | + Stack<Node> st = new Stack<Node>(); |
| 203 | + Node cur = this.root, temp2; |
| 204 | + while (cur != null || !st.empty()) { |
| 205 | + if (cur != null) { |
| 206 | + st.push(cur); |
| 207 | + cur = cur.left; |
| 208 | + } else { |
| 209 | + temp2 = st.peek(); |
| 210 | + if (temp2.right != null) { |
| 211 | + cur = temp2.right; |
| 212 | + } else { |
| 213 | + st.pop(); |
| 214 | + while (!st.empty() && st.peek().right == temp2) { |
| 215 | + System.out.print(temp2.data + " "); |
| 216 | + temp2 = st.pop(); |
| 217 | + } |
| 218 | + System.out.print(temp2.data + " "); |
| 219 | + } |
| 220 | + } |
| 221 | + } |
| 222 | + System.out.println(); // for next line |
| 223 | + } |
| 224 | + |
| 225 | + /** Method used to display preorder traversal of BST. */ |
| 226 | + public void preorder() { |
| 227 | + if (this.root == null) { |
| 228 | + System.out.println("This BST is empty."); |
| 229 | + return; |
| 230 | + } |
| 231 | + System.out.println("Preorder traversal of this tree is:"); |
| 232 | + Stack<Node> st = new Stack<Node>(); |
| 233 | + st.push(this.root); |
| 234 | + Node temp; |
| 235 | + while (!st.empty()) { |
| 236 | + temp = st.pop(); |
| 237 | + System.out.print(temp.data + " "); |
| 238 | + if (temp.right != null) { |
| 239 | + st.push(temp.right); |
| 240 | + } |
| 241 | + if (temp.left != null) { |
| 242 | + st.push(temp.left); |
| 243 | + } |
| 244 | + } |
| 245 | + System.out.println(); // for next line |
| 246 | + } |
| 247 | + |
| 248 | + /** |
| 249 | + * A method to check if given data exists in out Binary Search Tree. |
| 250 | + * |
| 251 | + * @param data the value that needs to be searched for |
| 252 | + * @return boolean representing if the value was find |
| 253 | + */ |
| 254 | + public boolean find(int data) { |
| 255 | + Node temp = this.root; |
| 256 | + /* Check if node exists |
| 257 | + */ |
| 258 | + while (temp != null) { |
| 259 | + if (temp.data > data) { |
| 260 | + temp = temp.left; |
| 261 | + } else if (temp.data < data) { |
| 262 | + temp = temp.right; |
| 263 | + } else { |
| 264 | + /* If found return true |
| 265 | + */ |
| 266 | + System.out.println(data + " is present in the BST."); |
| 267 | + return true; |
| 268 | + } |
| 269 | + } |
| 270 | + System.out.println(data + " not found."); |
| 271 | + return false; |
| 272 | + } |
| 273 | + |
| 274 | + /** The Node class used for building binary search tree */ |
| 275 | + private static class Node { |
| 276 | + int data; |
| 277 | + Node left; |
| 278 | + Node right; |
| 279 | + |
| 280 | + /** Constructor with data as parameter */ |
| 281 | + Node(int d) { |
| 282 | + data = d; |
| 283 | + left = null; |
| 284 | + right = null; |
| 285 | + } |
| 286 | + } |
| 287 | +} |
0 commit comments