Javaの最大ヒープ(Max Heap)とは?PriorityQueueを使った実装方法をわかりやすく解説
最大ヒープ(Max Heap)とは
最大ヒープは完全二分木の一種で、すべての親ノードの値が子ノードの値以上であるという性質を持つデータ構造です。この特性により、木の根(ルート)には常に最大の要素が配置されるため、優先度付きキューの実装などに広く活用されています。
Javaでは、標準ライブラリの java.util.PriorityQueue クラスに Collections.reverseOrder() を組み合わせるだけで、最大ヒープを簡単に実現できます。通常の PriorityQueue は最小ヒープとして動作しますが、逆順のコンパレータを渡すことで、最大値が常に先頭に来る構造に変更できるのです。
PriorityQueueを使った最大ヒープの実装例
以下は、ライブラリ関数を使用して最大ヒープを実装したサンプルコードです。
import java.util.*;
public class Demo{
public static void main(String args[]){
PriorityQueue<Integer> my_p_queue = new PriorityQueue<Integer>(Collections.reverseOrder());
my_p_queue.add(43);
my_p_queue.add(56);
my_p_queue.add(99);
System.out.println("優先度付きキューの要素 :");
Iterator my_iter = my_p_queue.iterator();
while (my_iter.hasNext())
System.out.println(my_iter.next());
my_p_queue.poll();
System.out.println("poll関数で要素を削除した後のキューの要素 :");
Iterator<Integer> my_iter_2 = my_p_queue.iterator();
while (my_iter_2.hasNext())
System.out.println(my_iter_2.next());
Object[] my_arr = my_p_queue.toArray();
System.out.println("最大ヒープの配列表現 :");
for (int i = 0; i < my_arr.length; i++)
System.out.println("値: " + my_arr[i].toString());
}
}
実行結果
優先度付きキューの要素 : 99 43 56 poll関数で要素を削除した後のキューの要素 : 56 43 最大ヒープの配列表現 : 値: 56 値: 43
コードの解説
Demo という名前のクラスには main メソッドが含まれています。main メソッド内では、まず Collections.reverseOrder() を引数に渡して PriorityQueue のインスタンスを生成し、add メソッドを使って 43、56、99 の3つの要素を追加しています。
次にイテレータを定義し、優先度付きキュー内の要素を順番に走査して表示します。ここで最初の要素として 99(最大値)が出力される点に注目してください。続いて poll メソッドを呼び出すと、キューの先頭にある最大値が削除されます。その後、残りの要素を再度走査して画面に表示し、最後に toArray メソッドでヒープの内容を配列形式に変換して出力しています。
補足:計算量と注意点
- 要素の追加(
add)や削除(poll)は、ヒープの再構築が必要となるため、計算量は O(log n) です。 - イテレータによる走査順序は、必ずしも降順にソートされた順序になるとは限りません。常に最大値を取得したい場合は
peekやpollを使用しましょう。 toArrayメソッドを使うことで、ヒープ内部の状態を配列として確認でき、デバッグにも役立ちます。
-
最大ヒープ(データ構造)から要素を削除するアルゴリズムをわかりやすく解説
ここでは、二分最大ヒープ(Binary Max Heap)というデータ構造から要素を削除する方法について解説します。まず、次のような初期状態の木を想定してください。 最大ヒープからの削除アルゴリズム 最大ヒープに対する削除操作では、通常「根(ルート)にある最大値を取り除く」処理を行います。削除後も親ノードは常に子ノード以上というヒープ条件を維持しなければならないため、単純に要素を取り除くだけでは不十分です。以下の擬似コードのように、末尾の要素を使ってヒープを再構成します。 delete(heap, n) − Begin if heap is empty, then exit
-
Pythonでリストが最大ヒープ(Max Heap)かどうかを判定する方法
数値のリスト nums が与えられたとき、そのリストが最大ヒープ(Max Heap)として成立しているかどうかを判定する問題について解説します。最大ヒープの条件リストが最大ヒープであるためには、以下のルールをすべて満たす必要があります。インデックス 2*i + 1 が範囲内に存在する場合、nums[i] >= nums[2*i + 1] が成り立つことインデックス 2*i + 2 が範囲内に存在する場合、nums[i] >= nums[2*i + 2] が成り立つことつまり、各親ノードの値が、その子ノードの値以上でなければなりません。これはヒープ構造の基本的な性質です。入力例と出力