Skip to content

Commit f8d14cc

Browse files
Adding RedBlackTree (#293)
1 parent 8c322a4 commit f8d14cc

File tree

7 files changed

+566
-8
lines changed

7 files changed

+566
-8
lines changed

pydatastructs/trees/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
BinaryIndexedTree,
1616
CartesianTree,
1717
Treap,
18-
SplayTree
18+
SplayTree,
19+
RedBlackTree
1920
)
2021
__all__.extend(binary_trees.__all__)
2122

pydatastructs/trees/binary_trees.py

Lines changed: 346 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from pydatastructs.utils import TreeNode, CartesianTreeNode
1+
from pydatastructs.utils import TreeNode, CartesianTreeNode, RedBlackTreeNode
22
from pydatastructs.miscellaneous_data_structures import Stack
33
from pydatastructs.linear_data_structures import (
44
OneDimensionalArray, DynamicOneDimensionalArray)
@@ -15,7 +15,8 @@
1515
'BinaryIndexedTree',
1616
'CartesianTree',
1717
'Treap',
18-
'SplayTree'
18+
'SplayTree',
19+
'RedBlackTree'
1920
]
2021

2122
class BinaryTree(object):
@@ -1057,6 +1058,349 @@ def split(self, x):
10571058
self.tree[self.root_idx].right = None
10581059
return other
10591060

1061+
class RedBlackTree(SelfBalancingBinaryTree):
1062+
"""
1063+
Represents Red Black trees.
1064+
1065+
Examples
1066+
========
1067+
1068+
>>> from pydatastructs.trees import RedBlackTree as RB
1069+
>>> b = RB()
1070+
>>> b.insert(1, 1)
1071+
>>> b.insert(2, 2)
1072+
>>> child = b.tree[b.root_idx].right
1073+
>>> b.tree[child].data
1074+
2
1075+
>>> b.search(1)
1076+
0
1077+
1078+
References
1079+
==========
1080+
1081+
.. [1] https://en.wikipedia.org/wiki/Red%E2%80%93black_tree
1082+
1083+
See Also
1084+
========
1085+
1086+
pydatastructs.trees.binary_tree.SelfBalancingBinaryTree
1087+
"""
1088+
1089+
@classmethod
1090+
def methods(cls):
1091+
return ['insert', 'delete']
1092+
1093+
def _get_parent(self, node_idx):
1094+
return self.tree[node_idx].parent
1095+
1096+
def _get_grand_parent(self, node_idx):
1097+
parent_idx=self._get_parent(node_idx)
1098+
return self.tree[parent_idx].parent
1099+
1100+
def _get_sibling(self, node_idx):
1101+
parent_idx=self._get_parent(node_idx)
1102+
if parent_idx is None:
1103+
return None
1104+
node = self.tree[parent_idx]
1105+
if node_idx==node.left:
1106+
sibling_idx=node.right
1107+
return sibling_idx
1108+
else:
1109+
sibling_idx=node.left
1110+
return sibling_idx
1111+
1112+
def _get_uncle(self, node_idx):
1113+
parent_idx=self._get_parent(node_idx)
1114+
return self._get_sibling(parent_idx)
1115+
1116+
def _is_onleft(self, node_idx):
1117+
parent = self._get_parent(node_idx)
1118+
if self.tree[parent].left == node_idx:
1119+
return True
1120+
return False
1121+
1122+
def _is_onright(self, node_idx):
1123+
if self._is_onleft(node_idx) is False:
1124+
return True
1125+
return False
1126+
1127+
def __fix_insert(self, node_idx):
1128+
while self._get_parent(node_idx) is not None and \
1129+
self.tree[self._get_parent(node_idx)].color == 1 and self.tree[node_idx].color==1:
1130+
parent_idx=self._get_parent(node_idx)
1131+
grand_parent_idx=self._get_grand_parent(node_idx)
1132+
uncle_idx = self._get_uncle(node_idx)
1133+
if uncle_idx is not None and self.tree[uncle_idx].color == 1:
1134+
self.tree[uncle_idx].color = 0
1135+
self.tree[parent_idx].color = 0
1136+
self.tree[grand_parent_idx].color = 1
1137+
node_idx= grand_parent_idx
1138+
else:
1139+
self.tree[self.root_idx].is_root=False
1140+
if self._is_onright(parent_idx):
1141+
if self._is_onleft(node_idx):
1142+
self._right_rotate(parent_idx, node_idx)
1143+
node_idx=parent_idx
1144+
parent_idx=self._get_parent(node_idx)
1145+
node_idx=parent_idx
1146+
parent_idx=self._get_parent(node_idx)
1147+
self._left_rotate(parent_idx, node_idx)
1148+
elif self._is_onleft(parent_idx):
1149+
if self._is_onright(node_idx):
1150+
self._left_rotate(parent_idx, node_idx)
1151+
node_idx=parent_idx
1152+
parent_idx=self._get_parent(node_idx)
1153+
node_idx=parent_idx
1154+
parent_idx=self._get_parent(node_idx)
1155+
self._right_rotate(parent_idx, node_idx)
1156+
self.tree[node_idx].color = 0
1157+
self.tree[parent_idx].color = 1
1158+
self.tree[self.root_idx].is_root=True
1159+
if self.tree[node_idx].is_root:
1160+
break
1161+
self.tree[self.root_idx].color=0
1162+
1163+
def insert(self, key, data=None):
1164+
super(RedBlackTree, self).insert(key, data)
1165+
node_idx = super(RedBlackTree, self).search(key)
1166+
node = self.tree[node_idx]
1167+
new_node = RedBlackTreeNode(key, data)
1168+
new_node.parent = node.parent
1169+
new_node.left = node.left
1170+
new_node.right = node.right
1171+
self.tree[node_idx] = new_node
1172+
if node.is_root:
1173+
self.tree[node_idx].is_root = True
1174+
self.tree[node_idx].color=0
1175+
elif self.tree[self.tree[node_idx].parent].color==1:
1176+
self.__fix_insert(node_idx)
1177+
1178+
def _find_predecessor(self, node_idx):
1179+
while self.tree[node_idx].right is not None:
1180+
node_idx = self.tree[node_idx].right
1181+
return node_idx
1182+
1183+
def _transplant_values(self, node_idx1, node_idx2):
1184+
parent = self.tree[node_idx1].parent
1185+
if self.tree[node_idx1].is_root and self._has_one_child(node_idx1):
1186+
self.tree[self.root_idx].key = self.tree[node_idx2].key
1187+
self.tree[self.root_idx].data = self.tree[node_idx2].data
1188+
self.tree[self.root_idx].left = self.tree[node_idx2].left
1189+
self.tree[self.root_idx].right = self.tree[node_idx2].right
1190+
self.tree[node_idx1].parent = None
1191+
return self.tree[self.root_idx].key
1192+
else:
1193+
self.tree[node_idx1].key = self.tree[node_idx2].key
1194+
self.tree[node_idx1].data = self.tree[node_idx2].data
1195+
1196+
def _has_one_child(self, node_idx):
1197+
if self._is_leaf(node_idx) is False and self._has_two_child(node_idx) is False:
1198+
return True
1199+
return False
1200+
1201+
def _is_leaf(self, node_idx):
1202+
if self.tree[node_idx].left is None and self.tree[node_idx].right is None:
1203+
return True
1204+
return False
1205+
1206+
def _has_two_child(self, node_idx):
1207+
if self.tree[node_idx].left is not None and self.tree[node_idx].right is not None:
1208+
return True
1209+
return False
1210+
1211+
def __has_red_child(self, node_idx):
1212+
left_idx = self.tree[node_idx].left
1213+
right_idx = self.tree[node_idx].right
1214+
if (left_idx is not None and self.tree[left_idx].color == 1) or \
1215+
(right_idx is not None and self.tree[right_idx].color == 1):
1216+
return True
1217+
return False
1218+
1219+
def _replace_node(self, node_idx):
1220+
if self._is_leaf(node_idx):
1221+
return None
1222+
elif self._has_one_child(node_idx):
1223+
if self.tree[node_idx].left is not None:
1224+
child = self.tree[node_idx].left
1225+
else:
1226+
child = self.tree[node_idx].right
1227+
return child
1228+
else:
1229+
return self._find_predecessor(self.tree[node_idx].left)
1230+
1231+
def __walk1_walk_isblack(self, color, node_idx1):
1232+
if (node_idx1 is None or self.tree[node_idx1].color == 0) and (color == 0):
1233+
return True
1234+
return False
1235+
1236+
def __left_left_siblingcase(self, node_idx):
1237+
left_idx = self.tree[node_idx].left
1238+
parent = self._get_parent(node_idx)
1239+
parent_color = self.tree[parent].color
1240+
self.tree[left_idx].color = self.tree[node_idx].color
1241+
self.tree[node_idx].color = parent_color
1242+
self._right_rotate(parent, node_idx)
1243+
1244+
def __right_left_siblingcase(self, node_idx):
1245+
left_idx = self.tree[node_idx].left
1246+
parent = self._get_parent(node_idx)
1247+
parent_color = self.tree[parent].color
1248+
self.tree[left_idx].color = parent_color
1249+
self._right_rotate(node_idx, left_idx)
1250+
child = self._get_parent(node_idx)
1251+
self._left_rotate(parent, child)
1252+
1253+
def __left_right_siblingcase(self, node_idx):
1254+
right_idx = self.tree[node_idx].right
1255+
parent = self._get_parent(node_idx)
1256+
parent_color = self.tree[parent].color
1257+
self.tree[right_idx].color = parent_color
1258+
self._left_rotate(node_idx, right_idx)
1259+
child = self._get_parent(node_idx)
1260+
self._right_rotate(parent, child)
1261+
1262+
def __right_right_siblingcase(self, node_idx):
1263+
right_idx = self.tree[node_idx].right
1264+
parent = self._get_parent(node_idx)
1265+
parent_color = self.tree[parent].color
1266+
self.tree[right_idx].color = self.tree[node_idx].color
1267+
self.tree[node_idx].color = parent_color
1268+
self._left_rotate(parent, node_idx)
1269+
1270+
def __fix_deletion(self, node_idx):
1271+
node = self.tree[node_idx]
1272+
color = node.color
1273+
while node_idx!= self.root_idx and color == 0:
1274+
sibling_idx = self._get_sibling(node_idx)
1275+
parent_idx = self._get_parent(node_idx)
1276+
if sibling_idx is None:
1277+
node_idx = parent_idx
1278+
continue
1279+
else:
1280+
if self.tree[sibling_idx].color == 1:
1281+
self.tree[self.root_idx].is_root = False
1282+
self.tree[parent_idx].color = 1
1283+
self.tree[sibling_idx].color = 0
1284+
if self._is_onleft(sibling_idx):
1285+
self._right_rotate(parent_idx, sibling_idx)
1286+
else:
1287+
self._left_rotate(parent_idx, sibling_idx)
1288+
self.tree[self.root_idx].is_root = True
1289+
continue
1290+
else:
1291+
if self.__has_red_child(sibling_idx):
1292+
self.tree[self.root_idx].is_root = False
1293+
left_idx = self.tree[sibling_idx].left
1294+
if self.tree[sibling_idx].left is not None and \
1295+
self.tree[left_idx].color == 1:
1296+
if self._is_onleft(sibling_idx):
1297+
self.__left_left_siblingcase(sibling_idx)
1298+
else:
1299+
self.__right_left_siblingcase(sibling_idx)
1300+
else:
1301+
if self._is_onleft(sibling_idx):
1302+
self.__left_right_siblingcase(sibling_idx)
1303+
else:
1304+
self.__right_right_siblingcase(sibling_idx)
1305+
self.tree[self.root_idx].is_root = True
1306+
self.tree[parent_idx].color = 0
1307+
else:
1308+
self.tree[sibling_idx].color = 1
1309+
if self.tree[parent_idx].color == 0:
1310+
node_idx = parent_idx
1311+
continue
1312+
else:
1313+
self.tree[parent_idx].color = 0
1314+
color = 1
1315+
1316+
def _remove_node(self, node_idx):
1317+
parent = self._get_parent(node_idx)
1318+
a = parent
1319+
if self._is_leaf(node_idx):
1320+
par_key, root_key = (self.tree[parent].key, self.tree[self.root_idx].key)
1321+
new_indices = self.tree.delete(node_idx)
1322+
if new_indices is not None:
1323+
a = new_indices[par_key]
1324+
self.root_idx = new_indices[root_key]
1325+
elif self._has_one_child(node_idx):
1326+
child = self._replace_node(node_idx)
1327+
parent = self._get_parent(node_idx)
1328+
par_key, root_key = (self.tree[parent].key, self.tree[self.root_idx].key)
1329+
new_indices = self.tree.delete(node_idx)
1330+
self._update_size(a)
1331+
1332+
def _delete_root(self, node_idx, node_idx1):
1333+
if self._is_leaf(node_idx):
1334+
self.tree[self.root_idx].data = None
1335+
self.tree[self.root_idx].key = None
1336+
elif self._has_one_child(node_idx):
1337+
root_key = self._transplant_values(node_idx, node_idx1)
1338+
new_indices = self.tree.delete(node_idx1)
1339+
if new_indices is not None:
1340+
self.root_idx = new_indices[root_key]
1341+
return
1342+
1343+
def __leaf_case(self, node_idx, node_idx1):
1344+
walk = node_idx
1345+
walk1 = node_idx1
1346+
parent = self._get_parent(node_idx)
1347+
color = self.tree[walk].color
1348+
if parent is None:
1349+
self._delete_root(walk, walk1)
1350+
else:
1351+
if self.__walk1_walk_isblack(color, walk1):
1352+
self.__fix_deletion(walk)
1353+
else:
1354+
sibling_idx = self._get_sibling(walk)
1355+
if sibling_idx is not None:
1356+
self.tree[sibling_idx].color = 1
1357+
if self._is_onleft(walk):
1358+
self.tree[parent].left = None
1359+
else:
1360+
self.tree[parent].right = None
1361+
self._remove_node(walk)
1362+
1363+
def __one_child_case(self, node_idx, node_idx1):
1364+
walk = node_idx
1365+
walk1 = node_idx1
1366+
walk_original_color = self.tree[walk].color
1367+
parent = self._get_parent(node_idx)
1368+
if parent is None:
1369+
self._delete_root(walk, walk1)
1370+
else:
1371+
if self._is_onleft(walk):
1372+
self.tree[parent].left = walk1
1373+
else:
1374+
self.tree[parent].right = walk1
1375+
self.tree[walk1].parent = parent
1376+
a = self._remove_node(walk)
1377+
if self.__walk1_walk_isblack(walk_original_color, walk1):
1378+
self.__fix_deletion(walk1)
1379+
else:
1380+
self.tree[walk1].color = 0
1381+
1382+
def __two_child_case(self, node_idx):
1383+
walk = node_idx
1384+
successor = self._replace_node(walk)
1385+
self._transplant_values(walk, successor)
1386+
walk = successor
1387+
walk1 = self._replace_node(walk)
1388+
return walk, walk1
1389+
1390+
def delete(self, key, **kwargs):
1391+
walk = super(RedBlackTree, self).search(key)
1392+
if walk is not None:
1393+
walk1 = self._replace_node(walk)
1394+
if self._has_two_child(walk):
1395+
walk, walk1 = self.__two_child_case(walk)
1396+
if self._is_leaf(walk):
1397+
self.__leaf_case(walk, walk1)
1398+
elif self._has_one_child(walk):
1399+
self.__one_child_case(walk, walk1)
1400+
return True
1401+
else:
1402+
return None
1403+
10601404
class BinaryTreeTraversal(object):
10611405
"""
10621406
Represents the traversals possible in

0 commit comments

Comments
 (0)