<一覧に戻る

ヒープ(優先度キュー)の概念と基本操作

ヒープは、特に優先度キューの実装に用いられる非常に効率的なデータ構造です。ヒープは完全二分木の特性を持ち、各ノードがその子ノードよりも優先度が高い(または低い)という特性を持っています。この特性により、最大値または最小値の取得が効率的に行えます。

ヒープの基本概念

ヒープには主に2つのタイプがあります。

  1. 最大ヒープ: 親ノードが子ノードよりも大きい(または等しい)という特性を持つ。
  2. 最小ヒープ: 親ノードが子ノードよりも小さい(または等しい)という特性を持つ。

ヒープを用いることで、優先度に基づいて要素を効率的に追加、削除、取得することができます。

ヒープの基本操作

ヒープにはいくつかの基本的な操作があります。

  • 挿入: 新しい要素をヒープに追加する。
  • 削除: ヒープの最上位の要素(最大または最小)を削除する。
  • 取得: ヒープの最上位の要素を取得する。
  • ヒープ化: ヒープの特性を維持するために、ノードを再配置する。

次に、Pythonでヒープを実装してみましょう。

ヒープの実装

以下は、最小ヒープの実装例です。

class MinHeap:
    def __init__(self):
        self.heap = []

    def insert(self, value):
        self.heap.append(value)
        self._heapify_up(len(self.heap) - 1)

    def delete_min(self):
        if len(self.heap) == 0:
            return None
        if len(self.heap) == 1:
            return self.heap.pop()

        min_value = self.heap[0]
        self.heap[0] = self.heap.pop()  # 最後の要素をルートに移動
        self._heapify_down(0)
        return min_value

    def get_min(self):
        return self.heap[0] if self.heap else None

    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 __str__(self):
        return str(self.heap)

コードの解説

  • __init__ メソッド: ヒープの初期化を行います。空のリストを作成します。
  • insert メソッド: 新しい値をヒープに追加し、ヒープの特性を保つために、_heapify_upメソッドを呼び出します。
  • delete_min メソッド: 最小値を削除し、最後の要素をルートに移動してから、_heapify_downメソッドを呼び出してヒープの特性を保ちます。
  • get_min メソッド: ヒープの最小の値を返します。
  • _heapify_up メソッド: 新しい要素が適切な位置に来るまで親ノードと入れ替えます。
  • _heapify_down メソッド: ヒープの特性を保つために、子ノードと入れ替えを行います。
  • __str__ メソッド: ヒープの内容を文字列として表示します。

ヒープの使用例

以下は、上記のMinHeapクラスを使用した例です。

if __name__ == "__main__":
    heap = MinHeap()
    heap.insert(10)
    heap.insert(4)
    heap.insert(15)
    heap.insert(20)
    heap.insert(3)

    print("Heap:", heap)

    print("Minimum value:", heap.get_min())
    print("Deleting minimum value:", heap.delete_min())
    print("Heap after deletion:", heap)

使用例の解説

  • ヒープを作成し、いくつかの整数を挿入します。
  • 現在のヒープの状態を表示します。
  • ヒープの最小値を取得して表示します。
  • 最小値を削除し、その後のヒープの状態を表示します。

このようにして、ヒープ(優先度キュー)の基本的な操作を理解し、実装することができます。ヒープは、スケジューリング問題やその他多くのアルゴリズムで非常に重要な役割を果たします。

出力結果: