Skip to content

Commit 0720c63

Browse files
committed
Added Binary Search Tree Implementation
1 parent a19a798 commit 0720c63

File tree

1 file changed

+371
-0
lines changed

1 file changed

+371
-0
lines changed

binary_search_tree.py

+371
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,371 @@
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

Comments
 (0)