Inserting nodes into a Red-Black Tree involves specific steps to ensure the tree maintains its balanced structure after each operation. A Red-Black Tree (RBT) is a self-balancing binary search tree, and insertion into it follows a process that ensures the tree properties remain valid. These properties include node colorings and balancing rules, which we need to uphold after adding a new node.
A Red-Black Tree (RBT) is a self-balancing binary search tree where each node contains an extra bit of information for its color. The color can be either red or black. These color properties ensure that the tree remains balanced, providing efficient time complexity for search, insert, and delete operations.
The Red-Black Tree has the following properties that are crucial for maintaining balance:
The insertion process in a Red-Black Tree is divided into two main parts:
The insertion process in a Red-Black Tree follows these key steps:
When a violation occurs after insertion, there are several cases to handle:
Below is a Python code implementation that demonstrates insertion into a Red-Black Tree:
class Node:
def __init__(self, data):
self.data = data
self.color = "RED" # New nodes are 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_insert(self, k):
while k.parent.color == "RED":
if k.parent == k.parent.parent.left:
u = k.parent.parent.right
if u.color == "RED":
u.color = "BLACK"
k.parent.color = "BLACK"
k.parent.parent.color = "RED"
k = k.parent.parent
else:
if k == k.parent.right:
k = k.parent
self.left_rotate(k)
k.parent.color = "BLACK"
k.parent.parent.color = "RED"
self.right_rotate(k.parent.parent)
else:
u = k.parent.parent.left
if u.color == "RED":
u.color = "BLACK"
k.parent.color = "BLACK"
k.parent.parent.color = "RED"
k = k.parent.parent
else:
if k == k.parent.left:
k = k.parent
self.right_rotate(k)
k.parent.color = "BLACK"
k.parent.parent.color = "RED"
self.left_rotate(k.parent.parent)
if k == self.root:
break
self.root.color = "BLACK"
def insert(self, key):
node = Node(key)
node.parent = None
node.data = key
node.left = self.TNULL
node.right = self.TNULL
node.color = "RED"
y = None
x = self.root
while x != self.TNULL:
y = x
if node.data < x.data:
x = x.left
else:
x = x.right
node.parent = y
if y == None:
self.root = node
elif node.data < y.data:
y.left = node
else:
y.right = node
if node.parent == None:
node.color = "BLACK"
return
if node.parent.parent == None:
return
self.fix_insert(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
print("In-order Traversal of Red-Black Tree:")
rb_tree.inorder(rb_tree.root)
Node Class:
data
field, a color
field (either "RED" or "BLACK"), and pointers to its left child, right child, and parent.TNULL
is used to represent leaves and simplifies boundary cases.RedBlackTree Class:
insert():
fix_insert()
to restore the Red-Black properties.inorder():