ヒープは、完全二分木の一種であり、特に優先度キューの実装において重要な役割を果たします。ヒープには主に最小ヒープと最大ヒープの2種類があります。最小ヒープでは親ノードが子ノードよりも小さい値を持ち、最大ヒープでは親ノードが子ノードよりも大きい値を持ちます。この教材では、Pythonを使用して最小ヒープと最大ヒープを実装します。
ヒープの基本操作には、以下のものがあります。
以下に最小ヒープの実装を示します。
class MinHeap:
def __init__(self):
self.heap = []
def insert(self, val):
self.heap.append(val)
self._heapify_up(len(self.heap) - 1)
def remove_min(self):
if len(self.heap) == 0:
return None
if len(self.heap) == 1:
return self.heap.pop()
min_val = self.heap[0]
self.heap[0] = self.heap.pop()
self._heapify_down(0)
return min_val
def _heapify_up(self, index):
parent_index = (index - 1) // 2
if index > 0 and self.heap[index] < self.heap[parent_index]:
self.heap[index], self.heap[parent_index] = self.heap[parent_index], self.heap[index]
self._heapify_up(parent_index)
def _heapify_down(self, index):
smallest = index
left_child_index = 2 * index + 1
right_child_index = 2 * index + 2
if left_child_index < len(self.heap) and self.heap[left_child_index] < self.heap[smallest]:
smallest = left_child_index
if right_child_index < len(self.heap) and self.heap[right_child_index] < self.heap[smallest]:
smallest = right_child_index
if smallest != index:
self.heap[index], self.heap[smallest] = self.heap[smallest], self.heap[index]
self._heapify_down(smallest)
def peek(self):
return self.heap[0] if self.heap else None
def is_empty(self):
return len(self.heap) == 0
MinHeap
クラスを定義しています。このクラスはリスト heap
を持ち、ヒープの要素を格納します。insert
メソッドでは、新しい値をヒープに追加し、ヒープの特性を維持するために _heapify_up
メソッドを呼び出します。remove_min
メソッドでは、最小値を削除し、ヒープの最後の要素をルートに移動し、ヒープの特性を維持するために _heapify_down
メソッドを呼び出します。_heapify_up
と _heapify_down
メソッドは、挿入または削除後にヒープの特性を維持するためにノードの位置を調整します。peek
メソッドは、ヒープの最小値を返しますが、削除はしません。is_empty
メソッドは、ヒープが空かどうかを判定します。次に、最大ヒープの実装を示します。
class MaxHeap:
def __init__(self):
self.heap = []
def insert(self, val):
self.heap.append(val)
self._heapify_up(len(self.heap) - 1)
def remove_max(self):
if len(self.heap) == 0:
return None
if len(self.heap) == 1:
return self.heap.pop()
max_val = self.heap[0]
self.heap[0] = self.heap.pop()
self._heapify_down(0)
return max_val
def _heapify_up(self, index):
parent_index = (index - 1) // 2
if index > 0 and self.heap[index] > self.heap[parent_index]:
self.heap[index], self.heap[parent_index] = self.heap[parent_index], self.heap[index]
self._heapify_up(parent_index)
def _heapify_down(self, index):
largest = index
left_child_index = 2 * index + 1
right_child_index = 2 * index + 2
if left_child_index < len(self.heap) and self.heap[left_child_index] > self.heap[largest]:
largest = left_child_index
if right_child_index < len(self.heap) and self.heap[right_child_index] > self.heap[largest]:
largest = right_child_index
if largest != index:
self.heap[index], self.heap[largest] = self.heap[largest], self.heap[index]
self._heapify_down(largest)
def peek(self):
return self.heap[0] if self.heap else None
def is_empty(self):
return len(self.heap) == 0
MaxHeap
クラスを定義し、最小ヒープと同様にリスト heap
を持ちます。insert
メソッドで新しい値を追加し、 _heapify_up
メソッドを呼び出します。remove_max
メソッドでは、最大値を削除し、最後の要素をルートに移動し、 _heapify_down
メソッドを呼び出します。_heapify_up
と _heapify_down
メソッドは、ヒープの特性を保つためにノードの位置を調整します。peek
メソッドは最大値を返します。is_empty
メソッドは、ヒープが空かどうかを判定します。このヒープの実装を使用してみましょう。
# 最小ヒープの使用例
min_heap = MinHeap()
min_heap.insert(3)
min_heap.insert(1)
min_heap.insert(2)
print(min_heap.peek()) # 1
print(min_heap.remove_min()) # 1
print(min_heap.peek()) # 2
# 最大ヒープの使用例
max_heap = MaxHeap()
max_heap.insert(3)
max_heap.insert(1)
max_heap.insert(2)
print(max_heap.peek()) # 3
print(max_heap.remove_max()) # 3
print(max_heap.peek()) # 2
MinHeap
クラスのインスタンスを作成し、いくつかの値を挿入します。peek
メソッドで最小値を取得し、remove_min
メソッドで最小値を削除します。MaxHeap
クラスのインスタンスを作成し、同様の操作を行います。以上で、最小ヒープと最大ヒープの実装とその使用例についての説明を終わります。ヒープの理解を深めることで、より高度なデータ構造やアルゴリズムに挑戦する準備が整います。