Skip to content

Commit 46e3441

Browse files
committed
Added a python program for implementaion of red-black trees
1 parent 17a483b commit 46e3441

File tree

1 file changed

+345
-0
lines changed

1 file changed

+345
-0
lines changed
Lines changed: 345 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,345 @@
1+
# Implementing Red-Black Tree in Python
2+
3+
4+
import sys
5+
6+
7+
# Node creation
8+
class Node():
9+
def __init__(self, item):
10+
self.item = item
11+
self.parent = None
12+
self.left = None
13+
self.right = None
14+
self.color = 1
15+
16+
17+
class RedBlackTree():
18+
def __init__(self):
19+
self.TNULL = Node(0)
20+
self.TNULL.color = 0
21+
self.TNULL.left = None
22+
self.TNULL.right = None
23+
self.root = self.TNULL
24+
25+
# Preorder
26+
def pre_order_helper(self, node):
27+
if node != TNULL:
28+
sys.stdout.write(node.item + " ")
29+
self.pre_order_helper(node.left)
30+
self.pre_order_helper(node.right)
31+
32+
# Inorder
33+
def in_order_helper(self, node):
34+
if node != TNULL:
35+
self.in_order_helper(node.left)
36+
sys.stdout.write(node.item + " ")
37+
self.in_order_helper(node.right)
38+
39+
# Postorder
40+
def post_order_helper(self, node):
41+
if node != TNULL:
42+
self.post_order_helper(node.left)
43+
self.post_order_helper(node.right)
44+
sys.stdout.write(node.item + " ")
45+
46+
# Search the tree
47+
def search_tree_helper(self, node, key):
48+
if node == TNULL or key == node.item:
49+
return node
50+
51+
if key < node.item:
52+
return self.search_tree_helper(node.left, key)
53+
return self.search_tree_helper(node.right, key)
54+
55+
# Balancing the tree after deletion
56+
def delete_fix(self, x):
57+
while x != self.root and x.color == 0:
58+
if x == x.parent.left:
59+
s = x.parent.right
60+
if s.color == 1:
61+
s.color = 0
62+
x.parent.color = 1
63+
self.left_rotate(x.parent)
64+
s = x.parent.right
65+
66+
if s.left.color == 0 and s.right.color == 0:
67+
s.color = 1
68+
x = x.parent
69+
else:
70+
if s.right.color == 0:
71+
s.left.color = 0
72+
s.color = 1
73+
self.right_rotate(s)
74+
s = x.parent.right
75+
76+
s.color = x.parent.color
77+
x.parent.color = 0
78+
s.right.color = 0
79+
self.left_rotate(x.parent)
80+
x = self.root
81+
else:
82+
s = x.parent.left
83+
if s.color == 1:
84+
s.color = 0
85+
x.parent.color = 1
86+
self.right_rotate(x.parent)
87+
s = x.parent.left
88+
89+
if s.right.color == 0 and s.right.color == 0:
90+
s.color = 1
91+
x = x.parent
92+
else:
93+
if s.left.color == 0:
94+
s.right.color = 0
95+
s.color = 1
96+
self.left_rotate(s)
97+
s = x.parent.left
98+
99+
s.color = x.parent.color
100+
x.parent.color = 0
101+
s.left.color = 0
102+
self.right_rotate(x.parent)
103+
x = self.root
104+
x.color = 0
105+
106+
def __rb_transplant(self, u, v):
107+
if u.parent == None:
108+
self.root = v
109+
elif u == u.parent.left:
110+
u.parent.left = v
111+
else:
112+
u.parent.right = v
113+
v.parent = u.parent
114+
115+
# Node deletion
116+
def delete_node_helper(self, node, key):
117+
z = self.TNULL
118+
while node != self.TNULL:
119+
if node.item == key:
120+
z = node
121+
122+
if node.item <= key:
123+
node = node.right
124+
else:
125+
node = node.left
126+
127+
if z == self.TNULL:
128+
print("Cannot find key in the tree")
129+
return
130+
131+
y = z
132+
y_original_color = y.color
133+
if z.left == self.TNULL:
134+
x = z.right
135+
self.__rb_transplant(z, z.right)
136+
elif (z.right == self.TNULL):
137+
x = z.left
138+
self.__rb_transplant(z, z.left)
139+
else:
140+
y = self.minimum(z.right)
141+
y_original_color = y.color
142+
x = y.right
143+
if y.parent == z:
144+
x.parent = y
145+
else:
146+
self.__rb_transplant(y, y.right)
147+
y.right = z.right
148+
y.right.parent = y
149+
150+
self.__rb_transplant(z, y)
151+
y.left = z.left
152+
y.left.parent = y
153+
y.color = z.color
154+
if y_original_color == 0:
155+
self.delete_fix(x)
156+
157+
# Balance the tree after insertion
158+
def fix_insert(self, k):
159+
while k.parent.color == 1:
160+
if k.parent == k.parent.parent.right:
161+
u = k.parent.parent.left
162+
if u.color == 1:
163+
u.color = 0
164+
k.parent.color = 0
165+
k.parent.parent.color = 1
166+
k = k.parent.parent
167+
else:
168+
if k == k.parent.left:
169+
k = k.parent
170+
self.right_rotate(k)
171+
k.parent.color = 0
172+
k.parent.parent.color = 1
173+
self.left_rotate(k.parent.parent)
174+
else:
175+
u = k.parent.parent.right
176+
177+
if u.color == 1:
178+
u.color = 0
179+
k.parent.color = 0
180+
k.parent.parent.color = 1
181+
k = k.parent.parent
182+
else:
183+
if k == k.parent.right:
184+
k = k.parent
185+
self.left_rotate(k)
186+
k.parent.color = 0
187+
k.parent.parent.color = 1
188+
self.right_rotate(k.parent.parent)
189+
if k == self.root:
190+
break
191+
self.root.color = 0
192+
193+
# Printing the tree
194+
def __print_helper(self, node, indent, last):
195+
if node != self.TNULL:
196+
sys.stdout.write(indent)
197+
if last:
198+
sys.stdout.write("R----")
199+
indent += " "
200+
else:
201+
sys.stdout.write("L----")
202+
indent += "| "
203+
204+
s_color = "RED" if node.color == 1 else "BLACK"
205+
print(str(node.item) + "(" + s_color + ")")
206+
self.__print_helper(node.left, indent, False)
207+
self.__print_helper(node.right, indent, True)
208+
209+
def preorder(self):
210+
self.pre_order_helper(self.root)
211+
212+
def inorder(self):
213+
self.in_order_helper(self.root)
214+
215+
def postorder(self):
216+
self.post_order_helper(self.root)
217+
218+
def searchTree(self, k):
219+
return self.search_tree_helper(self.root, k)
220+
221+
def minimum(self, node):
222+
while node.left != self.TNULL:
223+
node = node.left
224+
return node
225+
226+
def maximum(self, node):
227+
while node.right != self.TNULL:
228+
node = node.right
229+
return node
230+
231+
def successor(self, x):
232+
if x.right != self.TNULL:
233+
return self.minimum(x.right)
234+
235+
y = x.parent
236+
while y != self.TNULL and x == y.right:
237+
x = y
238+
y = y.parent
239+
return y
240+
241+
def predecessor(self, x):
242+
if (x.left != self.TNULL):
243+
return self.maximum(x.left)
244+
245+
y = x.parent
246+
while y != self.TNULL and x == y.left:
247+
x = y
248+
y = y.parent
249+
250+
return y
251+
252+
def left_rotate(self, x):
253+
y = x.right
254+
x.right = y.left
255+
if y.left != self.TNULL:
256+
y.left.parent = x
257+
258+
y.parent = x.parent
259+
if x.parent == None:
260+
self.root = y
261+
elif x == x.parent.left:
262+
x.parent.left = y
263+
else:
264+
x.parent.right = y
265+
y.left = x
266+
x.parent = y
267+
268+
def right_rotate(self, x):
269+
y = x.left
270+
x.left = y.right
271+
if y.right != self.TNULL:
272+
y.right.parent = x
273+
274+
y.parent = x.parent
275+
if x.parent == None:
276+
self.root = y
277+
elif x == x.parent.right:
278+
x.parent.right = y
279+
else:
280+
x.parent.left = y
281+
y.right = x
282+
x.parent = y
283+
284+
def insert(self, key):
285+
node = Node(key)
286+
node.parent = None
287+
node.item = key
288+
node.left = self.TNULL
289+
node.right = self.TNULL
290+
node.color = 1
291+
292+
y = None
293+
x = self.root
294+
295+
while x != self.TNULL:
296+
y = x
297+
if node.item < x.item:
298+
x = x.left
299+
else:
300+
x = x.right
301+
302+
node.parent = y
303+
if y == None:
304+
self.root = node
305+
elif node.item < y.item:
306+
y.left = node
307+
else:
308+
y.right = node
309+
310+
if node.parent == None:
311+
node.color = 0
312+
return
313+
314+
if node.parent.parent == None:
315+
return
316+
317+
self.fix_insert(node)
318+
319+
def get_root(self):
320+
return self.root
321+
322+
def delete_node(self, item):
323+
self.delete_node_helper(self.root, item)
324+
325+
def print_tree(self):
326+
self.__print_helper(self.root, "", True)
327+
328+
329+
if __name__ == "__main__":
330+
bst = RedBlackTree()
331+
332+
bst.insert(55)
333+
bst.insert(40)
334+
bst.insert(65)
335+
bst.insert(60)
336+
bst.insert(75)
337+
bst.insert(57)
338+
339+
bst.print_tree()
340+
341+
print("\nAfter deleting an element")
342+
bst.delete_node(40)
343+
bst.print_tree()
344+
345+

0 commit comments

Comments
 (0)