-
Notifications
You must be signed in to change notification settings - Fork 14
/
BinarySearchTree.py
160 lines (137 loc) · 4.85 KB
/
BinarySearchTree.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
class BSTNode:
def __init__(self,data):
self.data = data
self.leftChild = None
self.rightChild = None
def insertNode(rootNode, nodeValue): #Time - O(logN) Space-O(logN)
if rootNode.data == None:
rootNode.data = nodeValue
elif nodeValue <= rootNode.data:
if rootNode.leftChild is None:
rootNode.leftChild = BSTNode(nodeValue)
else:
insertNode(rootNode.leftChild, nodeValue)
else:
if rootNode.rightChild is None:
rootNode.rightChild = BSTNode(nodeValue)
else:
insertNode(rootNode.rightChild, nodeValue)
return "The node is succesfully inserted in the BST!"
def preOrderTraversal(rootNode): #Time - O(N) Space-O(N)
if not rootNode:
return
print(rootNode.data)
preOrderTraversal(rootNode.leftChild)
preOrderTraversal(rootNode.rightChild)
def InOrderTraversal(rootNode): #Time - O(N) Space-O(N)
if not rootNode:
return
InOrderTraversal(rootNode.leftChild)
print(rootNode.data)
InOrderTraversal(rootNode.rightChild)
def postOrderTraversal(rootNode): #Time - O(N) Space-O(N)
if not rootNode:
return
postOrderTraversal(rootNode.leftChild)
postOrderTraversal(rootNode.rightChild)
print(rootNode.data)
from collections import deque as queue
def levelOrderTraversal(rootNode): #Time - O(N) Space-O(N)
if not rootNode:
return
# Create an empty queue for
# level order traversal
q = queue()
# To store front element of
# queue.
#node *curr
# Enqueue Root and None node.
q.append(rootNode)
q.append(None)
while (len(q) > 1):
curr = q.popleft()
# Condition to check
# occurrence of next
# level.
if (curr == None):
q.append(None)
print()
else:
# Pushing left child of
# current node.
if (curr.leftChild):
q.append(curr.leftChild)
# Pushing right child of
# current node.
if (curr.rightChild):
q.append(curr.rightChild)
print(curr.data, end = " ")
def searchNode(rootNode, nodeValue): #Time - O(logN) Space-O(logN)
try:
if rootNode.data == nodeValue:
print(f"The value {nodeValue} is found at the root of the BST!")
elif nodeValue < rootNode.data:
if rootNode.leftChild.data == nodeValue:
print(f"The value {nodeValue} is found in the BST!")
else:
searchNode(rootNode.leftChild, nodeValue)
else:
if rootNode.rightChild.data == nodeValue:
print(f"The value {nodeValue} is found in the BST!")
else:
searchNode(rootNode.rightChild, nodeValue)
except AttributeError:
print(f"The value {nodeValue} does not exist in the BST! Please enter a valid entry!")
#helper func for deleting a node which has two children(can be parent too)
def minValueNode(bstNode):
curr = bstNode
while (curr.leftChild is not None):
curr = curr.leftChild
return curr
def deleteNode(rootNode, nodeValue): #Time - O(logN) Space-O(logN)
#0th case -base-case
if rootNode is None:
return rootNode
# 1st case - the node to be deleted is a leaf node
if nodeValue < rootNode.data:
rootNode.leftChild = deleteNode(rootNode.leftChild, nodeValue) #recursively call until leaf reached
elif nodeValue > rootNode.data:
rootNode.rightChild = deleteNode(rootNode.rightChild, nodeValue) #recursively call until leaf reached
# 2nd case - the node to be deleted has only 1 child node (can be parent too)
else:
if rootNode.leftChild is None:
temp = rootNode.rightChild
rootNode = None
return temp
if rootNode.rightChild is None:
temp = rootNode.leftChild
rootNode = None
return temp
# 3rd case - the node to be deleted has 2 children (can be parent too)
temp = minValueNode(rootNode.rightChild)
rootNode.data = temp.data
rootNode.rightChild = deleteNode(rootNode.rightChild, temp.data)
return rootNode
def deleteBST(rootNode): #Time - O(1) Space-O(1)
rootNode.data = None
rootNode.leftChild = None
rootNode.rightChild = None
return " The Binary Search Tree has been deleted!"
#Create a BST object - Time - O(1) Space-O(1)
newBST = BSTNode(None)
insertNode(newBST, 70)
insertNode(newBST, 50)
insertNode(newBST, 90)
insertNode(newBST, 30)
insertNode(newBST, 60)
insertNode(newBST, 80)
insertNode(newBST, 100)
insertNode(newBST, 20)
insertNode(newBST, 40)
preOrderTraversal(newBST)
InOrderTraversal(newBST)
postOrderTraversal(newBST)
levelOrderTraversal(newBST)
searchNode(newBST, 10)
deleteNode(newBST, 90)
levelOrderTraversal(newBST)