How to delete a node in a red-black tree
A red-black tree is a type of self-balancing binary tree. This Answer covers deletion in a red-black tree using Python.
Note: To read more about red-black trees, visit here.
Deletion
Deletion in a red-black tree is similar to a BST, except for one added step. If, after deletion, a red-black property is disrupted, the tree has to be recolored or rotated.
The process is as follows:
First, we find the node that we want to delete.
In case it is a leaf node, we just replace it with
None. Otherwise, we replace it with a leaf node, which must be a child with the minimum value. Then, we set it toNone.If the color properties are violated, we rebalance and recolor the tree.
Code example
Let's look at some code to see how it works.
class Node:def __init__(self, value, color=RED):self.value = valueself.left = Noneself.right = Noneself.parent = Noneself.color = colorclass RedBlackTree:def __init__(self):self.root = Noneself.none = Node(0, BLACK)def _min(self, node):while node.left != self.none:node = node.leftreturn nodedef delete(self, val):return self._delete(self.root, val)def _delete(self, node, val):temp = self.nonewhile node != self.none:if node.value == val:temp = nodeif node.value <= val:node = node.rightelse:node = node.leftif temp == self.none:return Falsetemp2 = temptemp2_original_color = temp2.colorif temp.left == self.none:temp3 = temp.rightself._rbt ( temp , temp.right )elif (temp.right == self.none):temp3 = temp.leftself._rbt ( temp , temp.left )else:temp2 = self.minimum ( temp.right )temp2_original_color = temp2.colortemp3 = temp2.rightif temp2.parent == temp:temp3.parent = temp2else:self._rbt ( temp2 , temp2.right )temp2.right = temp.righttemp2.right.parent = temp2self._rbt ( temp , temp2 )temp2.left = temp.lefttemp2.left.parent = temp2temp2.color = temp.colorif temp2_original_color == BLACK:self._fixDelete( temp3 )def _rbt(self, x, y):if not x.parent:self.root = yelif x == x.parent.left:x.parent.left = yelse:x.parent.right = yy.parent = x.parentdef _fixDelete(self, node):while node != self.root and node.color == BLACK:if node == node.parent.left:temp = node.parent.rightif temp.color == RED:temp.color = BLACKnode.parent.color = REDself.leftRotate(node.parent)temp = node.parent.rightif temp.left.color == BLACK and temp.right.color == BLACK:temp.color = REDnode = node.parentelse:if temp.right.color == BLACK:temp.left.color = BLACKtemp.color = REDself.rightRotate(temp)temp = node.parent.righttemp.color = node.parent.colornode.parent.color = BLACKtemp.right.color = BLACKself.leftRotate(node.parent)node = self.rootelse:temp = node.parent.leftif temp.color == RED:temp.color = BLACKnode.parent.color = REDself.rightRotate(node.parent)temp = node.parent.leftif temp.right.color == BLACK and temp.right.color == BLACK:temp.color = REDnode = node.parentelse:if temp.left.color == BLACK:temp.right.color = BLACKtemp.color = REDself.leftRotate(temp)temp = node.parent.lefttemp.color = node.parent.colornode.parent.color = BLACKtemp.left.color = BLACKself.rightRotate(node.parent)node = node.rootnode.color = BLACKdef leftRotate(self, node):right_child = node.rightnode.right = right_child.leftif right_child.left != self.none:right_child.left.parent = nodeif not node.parent:self.root = right_childelif node.parent.left == node:node.parent.left = right_childelse:node.parent.right = right_childright_child.parent = node.parentright_child.left = nodenode.parent = right_childdef rightRotate(self, node):left_child = node.leftnode.left = left_child.rightif left_child.right != self.none:left_child.right.parent = nodeif not node.parent:self.root = left_childelif node.parent.left == node:node.parent.left = left_childelse:node.parent.right = left_childleft_child.parent = node.parentleft_child.right = nodenode.parent = left_childtree = RedBlackTree()tree.root = Node(10, BLACK)tree.root.left = Node(5, BLACK)tree.root.left.parent = tree.roottree.root.right = Node(20, BLACK)tree.root.right.parent = tree.roottree.root.left.left = Node(1, BLACK)tree.root.left.left.parent = tree.root.lefttree.root.left.right = Node(7, BLACK)tree.root.left.right.parent = tree.root.lefttree.root.right.left = Node(15, BLACK)tree.root.right.left.parent = tree.root.righttree.root.right.right = Node(30, BLACK)tree.root.right.right.parent = tree.root.righttree.root.right.right.right = tree.nonetree.root.right.right.left = tree.nonetree.root.right.left.right = tree.nonetree.root.right.left.left = tree.nonetree.root.left.right.right = tree.nonetree.root.left.right.left = tree.nonetree.root.left.left.left = tree.nonetree.root.left.left.right = tree.nonetree.delete(7) # delete the treeprint(" ", tree.root.value, tree.root.color)print(" / \\")print(" ", tree.root.left.value, tree.root.left.color, " ", tree.root.right.value, tree.root.right.color)print(" / / \\")print("", tree.root.left.left.value, tree.root.left.left.color, " ", tree.root.right.left.value, tree.root.right.left.color, " ", tree.root.right.right.value, tree.root.right.right.color)
Explanation
Lines 1–7: We define a
Nodeclass that stores one node of the red-black tree.Lines 19–20: We define a
delete()function that calls the_delete()helper function.Lines 22–60: The
_delete()function first goes through the tree to find the node. It then deletes the node and checks if any properties are violated. If they are, it calls the_fixDelete()function.Lines 71–115: The
fixDelete()function rebalances and recolors the tree. It starts at the deleted node, and then goes up to the root until the tree is balanced again.Lines 151–180: We create a
tree, call thedelete()function on it, and print the resulting red-black tree.
Free Resources