プライオリティキューの明白な答えに加えて、ヒープはいつ私のプログラミングアドベンチャーに役立ちますか?
回答:
最大(または最小)の項目にすばやくアクセスする必要がある場合は常に使用してください。その項目は常に配列の最初の要素またはツリーのルートになるためです。
ただし、配列の残りの部分は部分的に並べ替えられていません。したがって、即時アクセスは最大(最小)のアイテムにのみ可能です。挿入は高速であるため、着信イベントまたはデータを処理し、常に最も早い/最大のイベントにアクセスできる優れた方法です。
優先キュー、スケジューラー(最初のアイテムが必要な場合)などに役立ちます。
ヒープは、親ノードの値がその子孫ノードの値よりも大きいツリーです。
ヒープを、ルートノードを最初に(次にそのノードの子を次に、次にそれらのノードの子を次に)深さの線形順に格納されたバイナリツリーと考える場合、次に、インデックスNのノードの子は2N + 1と2N + 2にあります。このプロパティにより、インデックスによる迅速なアクセスが可能になります。ヒープはノードを交換することによって操作されるため、これによりインプレースソートが可能になります。
ヒープは、最小値または最大値にすばやくアクセスできるようにするための構造です。
しかし、なぜそれが必要なのでしょうか。addのすべてのエントリをチェックして、それが最小か最大かを確認できます。このようにして、常に一定の時間で最小または最大を保持しO(1)
ます。
答えは、ヒープを使用すると、最小値または最大値を引き出し、次の最小値または最大値をすばやく知ることができるためです。これが優先キューと呼ばれる理由です。
年齢に基づいて患者が通う病院があるとします。最年長の人は、いつキューに入れられても、常に最初に出席します。
最も古いものを追跡することはできません。彼/彼女を引き抜くと、次に古いものを知らないからです。この病院の問題を解決するには、最大ヒープを実装します。このヒープは、定義により、部分的に順序付けられています。つまり、患者を年齢で並べ替えることはできませんが、最も古い患者が常に上位にあることがわかっているため、一定の時間で患者を引き出し、O(1)
ログ時間でヒープのバランスを再調整できますO(log N)
。
整数のシーケンスがあり、を追跡したいとしますmedian
。中央値は、順序付けられた配列の中央にある数値です。
例:
[1, 2, 5, 7, 23, 27, 31]
上記の場合、7
は中央値です。小さい数値を含む配列[1, 2, 5]
は、大きい数値を含む配列と同じサイズであるため[23, 27, 31]
です。通常、配列の要素数が奇数の場合、中央値は中央の2つの要素の算術平均です(5 + 7)/2
。
では、どのようにして中央値を追跡しますか?2つのヒープを持つことにより、現在の中央値よりも小さい数値を含む1分のヒープと、現在の中央値より大きい数値を含む最大ヒープ。これらのヒープが常にバランスしている場合、2つのヒープに同じ数の要素が含まれるか、1つの要素が他の要素よりも1つ多く、最も多くなります。
シーケンスに新しい要素を追加するときに、数値が現在の中央値よりも小さい場合は最小ヒープに追加し、それ以外の場合は最大ヒープに追加します。ここで、ヒープのバランスが取れていない場合(1つのヒープに他の要素よりも多くの要素がある)、最大のヒープから要素を引き出し、最小の要素に追加します。今ではバランスが取れています。
ヒープの特徴は、データが半順序に維持される構造であることです。したがって、これは完全な順序を維持するコストとランダムなカオスを検索するコストとの間の適切なトレードオフです。その特性は、選択、順序付け、分類などの多くのアルゴリズムで使用されます。
ヒープのもう1つの便利な特性は、配列からインプレースで作成できることです。