|
| 1 | +import sys |
| 2 | + |
| 3 | +class Node: |
| 4 | + """Class for node of a tree""" |
| 5 | + def __init__(self, info): |
| 6 | + """Initialising a node""" |
| 7 | + self.info = info |
| 8 | + self.left = None |
| 9 | + self.right = None |
| 10 | + # self.level = None |
| 11 | + |
| 12 | + def __str__(self): |
| 13 | + return str(self.info) |
| 14 | + |
| 15 | + def __del__(self): |
| 16 | + del self |
| 17 | + |
| 18 | + |
| 19 | +class BinarySearchTree: |
| 20 | + """Class for BST""" |
| 21 | + def __init__(self): |
| 22 | + """Initialising a BST""" |
| 23 | + self.root = None |
| 24 | + |
| 25 | + def insert(self, val): |
| 26 | + """Creating a BST with root value as val""" |
| 27 | + # Check if tree has root with None value |
| 28 | + if self.root is None: |
| 29 | + self.root = Node(val) |
| 30 | + # Here the tree already has one root |
| 31 | + else: |
| 32 | + current = self.root |
| 33 | + while True: |
| 34 | + if val < current.info: |
| 35 | + if current.left: |
| 36 | + current = current.left |
| 37 | + else: |
| 38 | + current.left = Node(val) |
| 39 | + break |
| 40 | + elif val > current.info: |
| 41 | + if current.right: |
| 42 | + current = current.right |
| 43 | + else: |
| 44 | + current.right = Node(val) |
| 45 | + break |
| 46 | + else: |
| 47 | + break |
| 48 | + |
| 49 | + def search(self, val, to_delete = False): |
| 50 | + current = self.root |
| 51 | + prev = -1 |
| 52 | + while current: |
| 53 | + if val < current.info: |
| 54 | + prev = current |
| 55 | + current = current.left |
| 56 | + elif val > current.info: |
| 57 | + prev = current |
| 58 | + current = current.right |
| 59 | + elif current.info == val: |
| 60 | + if not to_delete: |
| 61 | + return 'Match Found' |
| 62 | + return prev |
| 63 | + else: |
| 64 | + break |
| 65 | + if not to_delete: |
| 66 | + return 'Not Found' |
| 67 | + |
| 68 | + # Method to delete a tree-node if it exists, else error message will be returned. |
| 69 | + def delete(self, val): |
| 70 | + prev = self.search(val, True) |
| 71 | + # Check if node exists |
| 72 | + if prev is not None: |
| 73 | + # Check if node is the Root node |
| 74 | + if prev == -1: |
| 75 | + temp = self.root.left |
| 76 | + prev2 = None |
| 77 | + while temp.right: |
| 78 | + prev2 = temp |
| 79 | + temp = temp.right |
| 80 | + if prev2 is None: |
| 81 | + self.root.left = temp.left |
| 82 | + self.root.info = temp.info |
| 83 | + else: |
| 84 | + prev2.right = None |
| 85 | + self.root.info = temp.info |
| 86 | + print('Deleted Root ', val) |
| 87 | + # Check if node is to left of its parent |
| 88 | + elif prev.left and prev.left.info == val: |
| 89 | + # Check if node is leaf node |
| 90 | + if prev.left.left is prev.left.right: |
| 91 | + prev.left = None |
| 92 | + print('Deleted Node ', val) |
| 93 | + # Check if node has child at left and None at right |
| 94 | + elif prev.left.left and prev.left.right is None: |
| 95 | + prev.left = prev.left.left |
| 96 | + print('Deleted Node ', val) |
| 97 | + # Check if node has child at right and None at left |
| 98 | + elif prev.left.left is None and prev.left.right: |
| 99 | + prev.left = prev.left.right |
| 100 | + print('Deleted Node ', val) |
| 101 | + # Here node to be deleted has 2 children |
| 102 | + elif prev.left.left and prev.left.right: |
| 103 | + temp = prev.left |
| 104 | + while temp.right is not None: |
| 105 | + prev2 = temp |
| 106 | + temp = temp.right |
| 107 | + prev2.right = None |
| 108 | + prev.left.info = temp.info |
| 109 | + print('Deleted Node ', val) |
| 110 | + else: |
| 111 | + print('Error Left') |
| 112 | + |
| 113 | + |
| 114 | + # Check if node is to right of its parent |
| 115 | + elif prev.right.info == val: |
| 116 | + flag = 0 |
| 117 | + # Check is node is a leaf node |
| 118 | + if prev.right.left is prev.right.right: |
| 119 | + prev.right = None |
| 120 | + flag = 1 |
| 121 | + print('Deleted Node ', val) |
| 122 | + # Check if node has left child at None at right |
| 123 | + if prev.right and prev.right.left and prev.right.right is None: |
| 124 | + prev.right = prev.right.left |
| 125 | + print('Deleted Node ', val) |
| 126 | + # Check if node has right child at None at left |
| 127 | + elif prev.right and prev.right.left is None and prev.right.right: |
| 128 | + prev.right = prev.right.right |
| 129 | + print('Deleted Node ', val) |
| 130 | + elif prev.right and prev.right.left and prev.right.right: |
| 131 | + temp = prev.right |
| 132 | + while temp.left is not None: |
| 133 | + prev2 = temp |
| 134 | + temp = temp.left |
| 135 | + prev2.left = None |
| 136 | + prev.right.info = temp.info |
| 137 | + print('Deleted Node ', val) |
| 138 | + else: |
| 139 | + if flag == 0: |
| 140 | + print("Error") |
| 141 | + else: |
| 142 | + print("Node doesn't exists") |
| 143 | + |
| 144 | + def __str__(self): |
| 145 | + return 'Not able to print tree yet' |
| 146 | + |
| 147 | +def is_bst(node, lower_lim=None, upper_lim=None): |
| 148 | + """Function to find is a binary tree is a binary search tree.""" |
| 149 | + if lower_lim is not None and node.info < lower_lim: |
| 150 | + return False |
| 151 | + if upper_lim is not None and node.info > upper_lim: |
| 152 | + return False |
| 153 | + is_left_bst = True |
| 154 | + is_right_bst = True |
| 155 | + if node.left is not None: |
| 156 | + is_left_bst = is_bst(node.left, lower_lim, node.info) |
| 157 | + if is_left_bst and node.right is not None: |
| 158 | + is_right_bst = is_bst(node.right, node.info, upper_lim) |
| 159 | + return is_left_bst and is_right_bst |
| 160 | + |
| 161 | +def postorder(node): |
| 162 | + # L R N : Left , Right, Node |
| 163 | + if node is None: |
| 164 | + return |
| 165 | + if node.left: |
| 166 | + postorder(node.left) |
| 167 | + if node.right: |
| 168 | + postorder(node.right) |
| 169 | + print(node.info) |
| 170 | + |
| 171 | + |
| 172 | +def inorder(node): |
| 173 | + # L N R : Left, Node , Right |
| 174 | + if node is None: |
| 175 | + return |
| 176 | + if node.left: |
| 177 | + inorder(node.left) |
| 178 | + print(node.info) |
| 179 | + if node.right: |
| 180 | + inorder(node.right) |
| 181 | + |
| 182 | +def preorder(node): |
| 183 | + # N L R : Node , Left, Right |
| 184 | + if node is None: |
| 185 | + return |
| 186 | + print(node.info) |
| 187 | + if node.left: |
| 188 | + preorder(node.left) |
| 189 | + if node.right: |
| 190 | + preorder(node.right) |
| 191 | + |
| 192 | +# Levelwise |
| 193 | +def bfs(node): |
| 194 | + queue = [] |
| 195 | + if node: |
| 196 | + queue.append(node) |
| 197 | + while queue != []: |
| 198 | + temp = queue.pop(0) |
| 199 | + print(temp.info) |
| 200 | + if temp.left: |
| 201 | + queue.append(temp.left) |
| 202 | + if temp.right: |
| 203 | + queue.append(temp.right) |
| 204 | + |
| 205 | +def preorder_itr(node): |
| 206 | + # N L R : Node, Left , Right |
| 207 | + stack = [node] |
| 208 | + values = [] |
| 209 | + while stack != []: |
| 210 | + temp = stack.pop() |
| 211 | + print(temp.info) |
| 212 | + values.append(temp.info) |
| 213 | + if temp.right: |
| 214 | + stack.append(temp.right) |
| 215 | + if temp.left: |
| 216 | + stack.append(temp.left) |
| 217 | + return values |
| 218 | + |
| 219 | +def inorder_itr(node): |
| 220 | + # L N R : Left, Node, Right |
| 221 | + # 1) Create an empty stack S. |
| 222 | + # 2) Initialize current node as root |
| 223 | + # 3) Push the current node to S and set current = current->left until current is NULL |
| 224 | + # 4) If current is NULL and stack is not empty then |
| 225 | + # a) Pop the top item from stack. |
| 226 | + # b) Print the popped item, set current = popped_item->right |
| 227 | + # c) Go to step 3. |
| 228 | + # 5) If current is NULL and stack is empty then we are done. |
| 229 | + stack = [] |
| 230 | + current = node |
| 231 | + while True: |
| 232 | + if current != None: |
| 233 | + stack.append(current) # L |
| 234 | + current = current.left |
| 235 | + elif stack != []: |
| 236 | + temp = stack.pop() |
| 237 | + print(temp.info) # N |
| 238 | + current = temp.right # R |
| 239 | + else: |
| 240 | + break |
| 241 | + |
| 242 | +def postorder_itr(node): |
| 243 | + # L R N |
| 244 | + # 1. Push root to first stack. |
| 245 | + # 2. Loop while first stack is not empty |
| 246 | + # 2.1 Pop a node from first stack and push it to second stack |
| 247 | + # 2.2 Push left and right children of the popped node to first stack |
| 248 | + # 3. Print contents of second stack |
| 249 | + s1, s2 = [node], [] |
| 250 | + while s1 != []: |
| 251 | + temp = s1.pop() |
| 252 | + s2.append(temp) |
| 253 | + if temp.left: |
| 254 | + s1.append(temp.left) |
| 255 | + if temp.right: |
| 256 | + s1.append(temp.right) |
| 257 | + print(*(s2[::-1])) |
| 258 | + |
| 259 | +def bst_frm_pre(pre_list): |
| 260 | + box = Node(pre_list[0]) |
| 261 | + if len(pre_list) > 1: |
| 262 | + if len(pre_list) == 2: |
| 263 | + if pre_list[1] > pre_list[0]: |
| 264 | + box.right = Node(pre_list[1]) |
| 265 | + else: |
| 266 | + box.left = Node(pre_list[1]) |
| 267 | + else: |
| 268 | + all_less = False |
| 269 | + for i in range(1, len(pre_list)): |
| 270 | + if pre_list[i] > pre_list[0]: |
| 271 | + break |
| 272 | + else: |
| 273 | + all_less = True |
| 274 | + if i != 1: |
| 275 | + box.left = bst_frm_pre(pre_list[1 : i]) |
| 276 | + if not all_less: |
| 277 | + box.right = bst_frm_pre(pre_list[i:]) |
| 278 | + return box |
| 279 | + |
| 280 | +# Function to find the lowest common ancestor of nodes with values c1 and c2. |
| 281 | +# It return value in the lowest common ancestor, -1 indicates value returned for None. |
| 282 | +# Note that both values v1 and v2 should be present in the bst. |
| 283 | +def lca(t_node, c1, c2): |
| 284 | + if c1 == c2: |
| 285 | + return c1 |
| 286 | + current = t_node |
| 287 | + while current: |
| 288 | + if c1 < current.info and c2 < current.info: |
| 289 | + current = current.left |
| 290 | + elif c1 > current.info and c2 > current.info: |
| 291 | + current = current.right |
| 292 | + else: |
| 293 | + return current.info |
| 294 | + return -1 |
| 295 | + |
| 296 | +# Function to print element vertically which lie just below the root node |
| 297 | +def vertical_middle_level(t_node): |
| 298 | + e = (t_node, 0) # 0 indicates level 0, to left we have -ve and to right +ve |
| 299 | + queue = [e] |
| 300 | + ans = [] |
| 301 | + # Do a level-order traversal and assign level-value to each node |
| 302 | + while queue != []: |
| 303 | + temp, level = queue.pop(0) |
| 304 | + if level == 0: |
| 305 | + ans.append(str(temp.info)) |
| 306 | + if temp.left: |
| 307 | + queue.append((temp.left, level - 1)) |
| 308 | + if temp.right: |
| 309 | + queue.append((temp.right, level + 1)) |
| 310 | + return ' '.join(ans) |
| 311 | + |
| 312 | +def get_level(n, val): |
| 313 | + c_level = 0 |
| 314 | + |
| 315 | + while n.info != val: |
| 316 | + if val < n.info: |
| 317 | + n = n.left |
| 318 | + elif val > n.info: |
| 319 | + n = n.right |
| 320 | + c_level += 1 |
| 321 | + if n is None: |
| 322 | + return -1 |
| 323 | + |
| 324 | + return c_level |
| 325 | + |
| 326 | +def depth(node): |
| 327 | + if node is None: |
| 328 | + return 0 |
| 329 | + l_depth, r_depth = 0, 0 |
| 330 | + if node.left: |
| 331 | + l_depth = depth(node.left) |
| 332 | + if node.right: |
| 333 | + r_depth = depth(node.right) |
| 334 | + # print(node.info, l_depth, r_depth) |
| 335 | + return 1 + max(l_depth, r_depth) |
| 336 | + |
| 337 | + |
| 338 | +t = BinarySearchTree() |
| 339 | +t.insert(10) |
| 340 | +t.insert(5) |
| 341 | +t.insert(15) |
| 342 | +t.insert(3) |
| 343 | +t.insert(1) |
| 344 | +t.insert(0) |
| 345 | +t.insert(2) |
| 346 | +t.insert(7) |
| 347 | +t.insert(12) |
| 348 | +t.insert(18) |
| 349 | +t.insert(19) |
| 350 | +print(depth(t.root)) |
| 351 | +# inorder(t.root) |
| 352 | +# print() |
| 353 | +# print(t.search(5)) |
| 354 | +# t.delete(7) |
| 355 | +# t.delete(5) |
| 356 | +# t.delete(3) |
| 357 | +# t.delete(15) |
| 358 | +# inorder(t.root) |
| 359 | +# print() |
| 360 | +# t.delete(2) |
| 361 | +# t.delete(3) |
| 362 | +# t.delete(7) |
| 363 | +# t.delete(19) |
| 364 | +# t.delete(1) |
| 365 | +# inorder(t.root) |
| 366 | +# b = BinarySearchTree() |
| 367 | +# b.root = bst_frm_pre(preorder_itr(t.root)) |
| 368 | +# print(preorder_itr(b.root) == preorder_itr(t.root)) |
| 369 | +# print(lca(t.root, 3, 18)) |
| 370 | +# print(vertical_middle_level(t.root)) |
| 371 | +# print(get_level(t.root, 1)) |
0 commit comments