Skip to main content

Red-Black Tree

SpaceTime
AccessLookupInsertionDeletion
O(n)O(log n)O(log n)O(log n)O(log n)

Definition

Red-Black Tree is a type of self-balancing binary search tree that ensures the MAX height of any node is logarithmic and that no path from the root to any leaf node has more than a given number (usually 2) consecutive red nodes.

Simplified

Red-Black Tree is like a family tree with specific rules about the color of hats (red or black) each person wears. These rules ensure the tree remains balanced, which makes searching for a person (or data) efficient

Practice

AspectPseudo Code
Insertion
insert_rbtree(tree, key):
new_node = create_node(key)
uncle = ø
current_node = tree.root
while current_node != ø:
uncle = current_node
if new_node.key < current_node.key:
current_node = current_node.left_child
else:
current_node = current_node.right_child
new_node.parent = uncle
if uncle == ø:
tree.root = new_node
elif new_node.key < uncle.key:
uncle.left_child = new_node
else:
uncle.right_child = new_node

insert_fixup(tree, new_node)
tree.root.color = BLACK # Ensure the root is always black

create_node(key):
node = new Node()
node.key = key
node.color = RED
node.left_child = ø
node.right_child = ø
node.parent = ø
return node

left_rotate(tree, current_node):
uncle = current_node.right_child
current_node.right_child = uncle.left_child
if uncle.left_child != ø:
uncle.left_child.parent = current_node
uncle.parent = current_node.parent
if current_node.parent == ø:
tree.root = uncle
elif current_node == current_node.parent.left_child:
current_node.parent.left_child = uncle
else:
current_node.parent.right_child = uncle
uncle.left_child = current_node
current_node.parent = uncle

right_rotate(tree, uncle):
current_node = uncle.left_child
uncle.left_child = current_node.right_child
if current_node.right_child != ø:
current_node.right_child.parent = uncle
current_node.parent = uncle.parent
if uncle.parent == ø:
tree.root = current_node
elif uncle == uncle.parent.left_child:
uncle.parent.left_child = current_node
else:
uncle.parent.right_child = current_node
current_node.right_child = uncle
uncle.parent = current_node

insert_fixup(tree, new_node):
while new_node.parent != ø and new_node.parent.color == RED:
if new_node.parent == new_node.parent.parent.left_child:
grand_parent_child = new_node.parent.parent.right_child
if grand_parent_child != ø and grand_parent_child.color == RED:
new_node.parent.color = BLACK
grand_parent_child.color = BLACK
new_node.parent.parent.color = RED
new_node = new_node.parent.parent
else:
if new_node == new_node.parent.right_child:
new_node = new_node.parent
left_rotate(tree, new_node)
new_node.parent.color = BLACK
new_node.parent.parent.color = RED
right_rotate(tree, new_node.parent.parent)
else:
grand_parent_child = new_node.parent.parent.left_child
if grand_parent_child != ø and grand_parent_child.color == RED:
new_node.parent.color = BLACK
grand_parent_child.color = BLACK
new_node.parent.parent.color = RED
new_node = new_node.parent.parent
else:
if new_node == new_node.parent.left_child:
new_node = new_node.parent
right_rotate(tree, new_node)
new_node.parent.color = BLACK
new_node.parent.parent.color = RED
left_rotate(tree, new_node.parent.parent)
Deletion
delete_rbtree(tree, key):
node_to_delete = search(tree.root, key)
if node_to_delete == ø:
return

successor = node_to_delete
successor_original_color = successor.color
if node_to_delete.left_child == ø:
successor_child = node_to_delete.right_child
transplant(tree, node_to_delete, node_to_delete.right_child)
elif node_to_delete.right_child == ø:
successor_child = node_to_delete.left_child
transplant(tree, node_to_delete, node_to_delete.left_child)
else:
successor = find_min_node(node_to_delete.right_child)
successor_original_color = successor.color
successor_child = successor.right_child
if successor.parent == node_to_delete:
successor_child.parent = successor
else:
transplant(tree, successor, successor.right_child)
successor.right_child = node_to_delete.right_child
successor.right_child.parent = successor
transplant(tree, node_to_delete, successor)
successor.left_child = node_to_delete.left_child
successor.left_child.parent = successor
successor.color = node_to_delete.color
if successor_original_color == BLACK:
delete_fixup(tree, successor_child)

search(root, key):
current = root
while current != ø and current.key != key:
if key < current.key:
current = current.left_child
else:
current = current.right_child
return current

find_min_node(node):
while node.left_child != ø:
node = node.left_child
return node

transplant(tree, parent, child):
if parent.parent == ø:
tree.root = child
elif parent == parent.parent.left_child:
parent.parent.left_child = child
else:
parent.parent.right_child = child
if child != ø:
child.parent = parent.parent

delete_fixup(tree, current_node):
while current_node != tree.root and (current_node == ø or current_node.color == BLACK):
if current_node == current_node.parent.left_child:
current_node_sibling = current_node.parent.right_child
if current_node_sibling.color == RED:
current_node_sibling.color = BLACK
current_node.parent.color = RED
left_rotate(tree, current_node.parent)
current_node_sibling = current_node.parent.right_child
if (current_node_sibling.left_child == ø or current_node_sibling.left_child.color == BLACK) and (current_node_sibling.right_child == ø or current_node_sibling.right_child.color == BLACK):
current_node_sibling.color = RED
current_node = current_node.parent
else:
if current_node_sibling.right_child == ø or current_node_sibling.right_child.color == BLACK:
current_node_sibling.left_child.color = BLACK
current_node_sibling.color = RED
right_rotate(tree, current_node_sibling)
current_node_sibling = current_node.parent.right_child
current_node_sibling.color = current_node.parent.color
current_node.parent.color = BLACK
current_node_sibling.right_child.color = BLACK
left_rotate(tree, current_node.parent)
current_node = tree.root
else:
current_node_sibling = current_node.parent.left_child
if current_node_sibling.color == RED:
current_node_sibling.color = BLACK
current_node.parent.color = RED
right_rotate(tree, current_node.parent)
current_node_sibling = current_node.parent.left_child
if (current_node_sibling.right_child == ø or current_node_sibling.right_child.color == BLACK) and (current_node_sibling.left_child == ø or current_node_sibling.left_child.color == BLACK):
current_node_sibling.color = RED
current_node = current_node.parent
else:
if current_node_sibling.left_child == ø or current_node_sibling.left_child.color == BLACK:
current_node_sibling.right_child.color = BLACK
current_node_sibling.color = RED
left_rotate(tree, current_node_sibling)
current_node_sibling = current_node.parent.left_child
current_node_sibling.color = current_node.parent.color
current_node.parent.color = BLACK
current_node_sibling.left_child.color = BLACK
right_rotate(tree, current_node.parent)
current_node = tree.root