C++で最大ヒープから最小値の要素を見つける方法
問題の概要
最大ヒープ(max heap)の中から、最も小さい値を持つ要素を探す方法を解説します。
以下のような最大ヒープを例に考えてみましょう。

最大ヒープでは、親ノードの値は必ずその子ノードの値以上になります。この性質により、最小値は必ず葉ノード(leaf node)のいずれかに存在すると結論できます。ヒープが n 個のノードを含む場合、葉ノードの数は ceil(n/2) 個になります。
また、最大ヒープは完全二分木であるため、配列として表現することができます。このとき、最初の葉ノードは floor(n/2) のインデックス以降に配置されます。上記の例では、最初の葉ノードはインデックス 5 に存在します。
アルゴリズム
最大ヒープから最小値を見つけるには、以下の手順を使用します。
1. ヒープ内の最初の葉ノードを見つけ、その値を最小値とする 2. 残りのすべての葉ノードを走査し、より小さい値を持つ葉が見つかれば最小値を更新する
C++での実装例
#include <iostream>
#define SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
using namespace std;
int getMinElement(int *heap, int n){
int minElement = heap[n / 2];
for (int i = n / 2 + 1; i < n; ++i) {
minElement = min(minElement, heap[i]);
}
return minElement;
}
int main(){
int heap[] = {120, 90, 100, 70, 75, 80, 60, 25, 40, 35};
cout << "Min value: " << getMinElement(heap, SIZE(heap)) << "\n";
return 0;
}実行結果
上記のプログラムをコンパイルして実行すると、次の出力が得られます。
Min value: 25
計算量について
このアルゴリズムは、葉ノードのみを走査するため、ノード総数 n の約半分の要素を調べることになります。したがって時間計算量は O(n/2)、すなわち O(n) となります。追加のメモリは不要で、空間計算量は O(1) です。最大ヒープの構造上、ルートから辿るだけでは最小値を特定できないため、このように葉ノード全体を確認するのが効率的なアプローチです。
-
C++で学ぶ二項ヒープ(Binomial Heap)の基礎と操作
二項ヒープ(Binomial Heap)とは、二分ヒープ(Binary Heap)を拡張したデータ構造です。二分ヒープが提供する各種操作に加えて、より高速なマージ(union)操作を実現できる点が大きな特徴です。二項ヒープは、複数の二項木(Binomial Tree)のコレクションとして表現されます。二項木(Binomial Tree)とは?次数kの二項木は、次数k-1の二項木を2つ用意し、一方をもう一方の最左の子として連結することで構築できます。次数kの二項木には、以下のような性質があります。ノードの総数は正確に2k個である。木の深さはkである。深さi(i = 0, 1, ..., k)には
-
C++のlog1p()関数とは?使い方とサンプルコードをわかりやすく解説
C++のlog1p()関数の概要C++のlog1p()関数は、任意の数値 a に対して「(a + 1) の自然対数(底が e の対数)」を計算するための関数です。戻り値として (a+1) の自然対数の値が返されます。なお、引数に -1 未満の値 を渡した場合は、有効な結果が得られないため NaN(Not a Number) が返される点に注意が必要です。数学的な表現log1p() の動作は、次の数式で表すことができます。log1p(a) = base-e log(a+1)log1p()の構文C++における log1p() 関数の構文は以下のとおりです。float log1p(float var