Skip to content

Commit 9dfd0a6

Browse files
authored
Merge pull request TheAlgorithms#200 from pablo9891/master
Added delete function to binary_search_tree.py and print function
2 parents ac33016 + 9d88246 commit 9dfd0a6

File tree

1 file changed

+151
-24
lines changed

1 file changed

+151
-24
lines changed

data_structures/Binary Tree/binary_search_tree.py

+151-24
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
'''
22
A binary search Tree
33
'''
4-
54
class Node:
65

7-
def __init__(self, label):
6+
def __init__(self, label, parent):
87
self.label = label
98
self.left = None
109
self.right = None
10+
#Added in order to delete a node easier
11+
self.parent = parent
1112

1213
def getLabel(self):
1314
return self.label
@@ -27,6 +28,11 @@ def getRight(self):
2728
def setRight(self, right):
2829
self.right = right
2930

31+
def getParent(self):
32+
return self.parent
33+
34+
def setParent(self, parent):
35+
self.parent = parent
3036

3137
class BinarySearchTree:
3238

@@ -35,13 +41,12 @@ def __init__(self):
3541

3642
def insert(self, label):
3743
# Create a new Node
38-
new_node = Node(label)
44+
new_node = Node(label, None)
3945
# If Tree is empty
4046
if self.empty():
4147
self.root = new_node
4248
else:
4349
#If Tree is not empty
44-
parent_node = None
4550
curr_node = self.root
4651
#While we don't get to a leaf
4752
while curr_node is not None:
@@ -58,7 +63,34 @@ def insert(self, label):
5863
if new_node.getLabel() < parent_node.getLabel():
5964
parent_node.setLeft(new_node)
6065
else:
61-
parent_node.setRight(new_node)
66+
parent_node.setRight(new_node)
67+
#Set parent to the new node
68+
new_node.setParent(parent_node)
69+
70+
def delete(self, label):
71+
if (not self.empty()):
72+
#Look for the node with that label
73+
node = self.getNode(label)
74+
#If the node exists
75+
if(node is not None):
76+
#If it has no children
77+
if(node.getLeft() is None and node.getRight() is None):
78+
self.__reassignNodes(node, None)
79+
node = None
80+
#Has only right children
81+
elif(node.getLeft() is None and node.getRight() is not None):
82+
self.__reassignNodes(node, node.getRight())
83+
#Has only left children
84+
elif(node.getLeft() is not None and node.getRight() is None):
85+
self.__reassignNodes(node, node.getLeft())
86+
#Has two children
87+
else:
88+
#Gets the max value of the left branch
89+
tmpNode = self.getMax(node.getLeft())
90+
#Deletes the tmpNode
91+
self.delete(tmpNode.getLabel())
92+
#Assigns the value to the node to delete and keesp tree structure
93+
node.setLabel(tmpNode.getLabel())
6294

6395
def getNode(self, label):
6496
curr_node = None
@@ -78,45 +110,121 @@ def getNode(self, label):
78110
curr_node = curr_node.getRight()
79111
return curr_node
80112

113+
def getMax(self, root = None):
114+
if(root is not None):
115+
curr_node = root
116+
else:
117+
#We go deep on the right branch
118+
curr_node = self.getRoot()
119+
if(not self.empty()):
120+
while(curr_node.getRight() is not None):
121+
curr_node = curr_node.getRight()
122+
return curr_node
123+
124+
def getMin(self, root = None):
125+
if(root is not None):
126+
curr_node = root
127+
else:
128+
#We go deep on the left branch
129+
curr_node = self.getRoot()
130+
if(not self.empty()):
131+
curr_node = self.getRoot()
132+
while(curr_node.getLeft() is not None):
133+
curr_node = curr_node.getLeft()
134+
return curr_node
135+
81136
def empty(self):
82137
if self.root is None:
83138
return True
84139
return False
85140

86-
def preShow(self, curr_node):
141+
def __InOrderTraversal(self, curr_node):
142+
nodeList = []
87143
if curr_node is not None:
88-
print(curr_node.getLabel())
89-
self.preShow(curr_node.getLeft())
90-
self.preShow(curr_node.getRight())
144+
nodeList.insert(0, curr_node)
145+
nodeList = nodeList + self.__InOrderTraversal(curr_node.getLeft())
146+
nodeList = nodeList + self.__InOrderTraversal(curr_node.getRight())
147+
return nodeList
91148

92149
def getRoot(self):
93150
return self.root
94151

95-
'''
96-
Example
97-
8
98-
/ \
99-
3 10
100-
/ \ \
101-
1 6 14
102-
/ \ /
103-
4 7 13
104-
'''
152+
def __isRightChildren(self, node):
153+
if(node == node.getParent().getRight()):
154+
return True
155+
return False
105156

157+
def __reassignNodes(self, node, newChildren):
158+
if(newChildren is not None):
159+
newChildren.setParent(node.getParent())
160+
if(node.getParent() is not None):
161+
#If it is the Right Children
162+
if(self.__isRightChildren(node)):
163+
node.getParent().setRight(newChildren)
164+
else:
165+
#Else it is the left children
166+
node.getParent().setLeft(newChildren)
106167

107-
if __name__ == "__main__":
168+
#This function traversal the tree. By default it returns an
169+
#In order traversal list. You can pass a function to traversal
170+
#The tree as needed by client code
171+
def traversalTree(self, traversalFunction = None, root = None):
172+
if(traversalFunction is None):
173+
#Returns a list of nodes in preOrder by default
174+
return self.__InOrderTraversal(self.root)
175+
else:
176+
#Returns a list of nodes in the order that the users wants to
177+
return traversalFunction(self.root)
178+
179+
#Returns an string of all the nodes labels in the list
180+
#In Order Traversal
181+
def __str__(self):
182+
list = self.__InOrderTraversal(self.root)
183+
str = ""
184+
for x in list:
185+
str = str + " " + x.getLabel().__str__()
186+
return str
187+
188+
def InPreOrder(curr_node):
189+
nodeList = []
190+
if curr_node is not None:
191+
nodeList = nodeList + InPreOrder(curr_node.getLeft())
192+
nodeList.insert(0, curr_node.getLabel())
193+
nodeList = nodeList + InPreOrder(curr_node.getRight())
194+
return nodeList
195+
196+
def testBinarySearchTree():
197+
'''
198+
Example
199+
8
200+
/ \
201+
3 10
202+
/ \ \
203+
1 6 14
204+
/ \ /
205+
4 7 13
206+
'''
207+
208+
'''
209+
Example After Deletion
210+
7
211+
/ \
212+
1 4
213+
214+
'''
108215
t = BinarySearchTree()
109216
t.insert(8)
110217
t.insert(3)
111-
t.insert(1)
112218
t.insert(6)
113-
t.insert(4)
114-
t.insert(7)
219+
t.insert(1)
115220
t.insert(10)
116221
t.insert(14)
117222
t.insert(13)
223+
t.insert(4)
224+
t.insert(7)
118225

119-
t.preShow(t.getRoot())
226+
#Prints all the elements of the list in order traversal
227+
print(t.__str__())
120228

121229
if(t.getNode(6) is not None):
122230
print("The label 6 exists")
@@ -128,3 +236,22 @@ def getRoot(self):
128236
else:
129237
print("The label -1 doesn't exist")
130238

239+
if(not t.empty()):
240+
print("Max Value: ", t.getMax().getLabel())
241+
print("Min Value: ", t.getMin().getLabel())
242+
243+
t.delete(13)
244+
t.delete(10)
245+
t.delete(8)
246+
t.delete(3)
247+
t.delete(6)
248+
t.delete(14)
249+
250+
#Gets all the elements of the tree In pre order
251+
#And it prints them
252+
list = t.traversalTree(InPreOrder, t.root)
253+
for x in list:
254+
print(x)
255+
256+
if __name__ == "__main__":
257+
testBinarySearchTree()

0 commit comments

Comments
 (0)