赤黒木は自己平衡二分探索木の一種であり、検索、挿入、削除の操作を効率的に行うことができます。赤黒木は、特にデータ構造が頻繁に変更される状況下でのパフォーマンスを最適化するために設計されています。この教材では、赤黒木の基本概念、特性、および実装方法について詳しく説明します。
赤黒木は以下の特性を持つ二分探索木です:
これらの特性により、赤黒木は常に平衡を保つことができ、最悪の場合でも操作の時間計算量はO(log n)となります。
赤黒木は以下のような場面で特に有用です:
以下にPythonでの赤黒木の基本的な実装を示します。この実装では、挿入操作を中心に解説します。
class Node:
def __init__(self, data):
self.data = data
self.color = 'red' # 新しいノードは赤
self.left = None
self.right = None
self.parent = None
class RedBlackTree:
def __init__(self):
self.NIL = Node(None) # 特殊な葉ノード
self.NIL.color = 'black'
self.root = self.NIL
def insert(self, data):
new_node = Node(data)
new_node.left = self.NIL
new_node.right = self.NIL
# 挿入する場所を見つける
parent = None
current = self.root
while current != self.NIL:
parent = current
if new_node.data < current.data:
current = current.left
else:
current = current.right
new_node.parent = parent
if parent is None: # 木が空の場合
self.root = new_node
elif new_node.data < parent.data:
parent.left = new_node
else:
parent.right = new_node
self.fix_insert(new_node)
def fix_insert(self, node):
while node != self.root and node.parent.color == 'red':
if node.parent == node.parent.parent.left:
uncle = node.parent.parent.right
if uncle.color == 'red': # Case 1: Uncle is red
node.parent.color = 'black'
uncle.color = 'black'
node.parent.parent.color = 'red'
node = node.parent.parent
else: # Case 2 and Case 3
if node == node.parent.right:
node = node.parent
self.left_rotate(node)
node.parent.color = 'black'
node.parent.parent.color = 'red'
self.right_rotate(node.parent.parent)
else:
uncle = node.parent.parent.left
if uncle.color == 'red': # Case 1: Uncle is red
node.parent.color = 'black'
uncle.color = 'black'
node.parent.parent.color = 'red'
node = node.parent.parent
else: # Case 2 and Case 3
if node == node.parent.left:
node = node.parent
self.right_rotate(node)
node.parent.color = 'black'
node.parent.parent.color = 'red'
self.left_rotate(node.parent.parent)
self.root.color = 'black'
def left_rotate(self, node):
right_child = node.right
node.right = right_child.left
if right_child.left != self.NIL:
right_child.left.parent = node
right_child.parent = node.parent
if node.parent is None:
self.root = right_child
elif node == node.parent.left:
node.parent.left = right_child
else:
node.parent.right = right_child
right_child.left = node
node.parent = right_child
def right_rotate(self, node):
left_child = node.left
node.left = left_child.right
if left_child.right != self.NIL:
left_child.right.parent = node
left_child.parent = node.parent
if node.parent is None:
self.root = left_child
elif node == node.parent.right:
node.parent.right = left_child
else:
node.parent.left = left_child
left_child.right = node
node.parent = left_child
def inorder(self, node):
if node != self.NIL:
self.inorder(node.left)
print(node.data, end=' ')
self.inorder(node.right)
# 使用例
if __name__ == "__main__":
rbt = RedBlackTree()
numbers = [10, 20, 30, 15, 25]
for num in numbers:
rbt.insert(num)
print("Inorder Traversal of Red Black Tree:")
rbt.inorder(rbt.root) # 出力: 10 15 20 25 30
この実装を通じて、赤黒木の挿入操作とその後の修正プロセスを理解することができます。赤黒木は、挿入や削除が頻繁に行われる場合に効率的に動作するデータ構造です。