Deleting a node from a Red-Black Tree (RBT) is more complex than insertion because it requires maintaining the tree's balancing properties. Just like insertion, deletion might violate one or more of the Red-Black Tree properties, such as the black height or the red node property. These violations must be fixed using rotations and color changes to restore the tree's balance.
A Red-Black Tree (RBT) is a self-balancing binary search tree where each node is colored either red or black. These color properties help maintain balance, ensuring that operations such as insertion, deletion, and searching have a time complexity of O(log n).
A Red-Black Tree satisfies the following properties:
The process of deleting a node from a Red-Black Tree involves the following steps:
Here are the steps to delete a node from a Red-Black Tree:
When a node is deleted, it might cause one of the following cases:
These cases continue recursively until the tree is balanced again.
Below is a Python implementation that demonstrates deletion in a Red-Black Tree. This code will show how to handle various cases of deletions and fix the tree's balance after the removal of a node.
class Node:
def __init__(self, data):
self.data = data
self.color = "RED" # New nodes are always inserted as red
self.left = None
self.right = None
self.parent = None
class RedBlackTree:
def __init__(self):
self.TNULL = Node(0) # Sentinel node for leaves
self.TNULL.color = "BLACK"
self.root = self.TNULL
def left_rotate(self, x):
y = x.right
x.right = y.left
if y.left != self.TNULL:
y.left.parent = x
y.parent = x.parent
if x.parent == self.TNULL:
self.root = y
elif x == x.parent.left:
x.parent.left = y
else:
x.parent.right = y
y.left = x
x.parent = y
def right_rotate(self, x):
y = x.left
x.left = y.right
if y.right != self.TNULL:
y.right.parent = x
y.parent = x.parent
if x.parent == self.TNULL:
self.root = y
elif x == x.parent.right:
x.parent.right = y
else:
x.parent.left = y
y.right = x
x.parent = y
def fix_delete(self, x):
while x != self.root and x.color == "BLACK":
if x == x.parent.left:
w = x.parent.right
if w.color == "RED":
w.color = "BLACK"
x.parent.color = "RED"
self.left_rotate(x.parent)
w = x.parent.right
if w.left.color == "BLACK" and w.right.color == "BLACK":
w.color = "RED"
x = x.parent
else:
if w.right.color == "BLACK":
w.left.color = "BLACK"
w.color = "RED"
self.right_rotate(w)
w = x.parent.right
w.color = x.parent.color
x.parent.color = "BLACK"
w.right.color = "BLACK"
self.left_rotate(x.parent)
x = self.root
else:
w = x.parent.left
if w.color == "RED":
w.color = "BLACK"
x.parent.color = "RED"
self.right_rotate(x.parent)
w = x.parent.left
if w.right.color == "BLACK" and w.left.color == "BLACK":
w.color = "RED"
x = x.parent
else:
if w.left.color == "BLACK":
w.right.color = "BLACK"
w.color = "RED"
self.left_rotate(w)
w = x.parent.left
w.color = x.parent.color
x.parent.color = "BLACK"
w.left.color = "BLACK"
self.right_rotate(x.parent)
x = self.root
x.color = "BLACK"
def delete(self, node, key):
z = self.TNULL
while node != self.TNULL:
if node.data == key:
z = node
if node.data <= key:
node = node.right
else:
node = node.left
if z == self.TNULL:
print("Node not found in the tree")
return
y = z
y_original_color = y.color
if z.left == self.TNULL:
x = z.right
self.transplant(z, z.right)
elif z.right == self.TNULL:
x = z.left
self.transplant(z, z.left)
else:
y = self.tree_minimum(z.right)
y_original_color = y.color
x = y.right
if y.parent == z:
x.parent = y
else:
self.transplant(y, y.right)
y.right = z.right
y.right.parent = y
self.transplant(z, y)
y.left = z.left
y.left.parent = y
y.color = z.color
if y_original_color == "BLACK":
self.fix_delete(x)
def transplant(self, u, v):
if u.parent == self.TNULL:
self.root = v
elif u == u.parent.left:
u.parent.left = v
else:
u.parent.right = v
v.parent = u.parent
def tree_minimum(self, node):
while node.left != self.TNULL:
node = node.left
return node
def inorder(self, root):
if root != self.TNULL:
self.inorder(root.left)
print(root.data, end=" ")
self.inorder(root.right)
# Example Usage
rb_tree = RedBlackTree()
# Insert keys into the Red-Black Tree
keys = [20, 15, 25, 10, 5, 1]
for key in keys:
rb_tree.insert(key)
# In-order traversal of the Red-Black Tree before deletion
print("In-order Traversal of Red-Black Tree before deletion:")
rb_tree.inorder(rb_tree.root)
# Delete node with key 10
rb_tree.delete(rb_tree.root, 10)
# In-order traversal of the Red-Black Tree after deletion
print("\nIn-order Traversal of Red-Black Tree after deletion:")
rb_tree.inorder(rb_tree.root)
Node Class:
Node
class contains data
, color
, left
, right
, and parent
attributes. It represents a node in the Red-Black Tree.RedBlackTree Class:
delete:
transplant:
inorder: