いつヒープを使用したいですか?


89

プライオリティキューの明白な答えに加えて、ヒープはいつ私のプログラミングアドベンチャーに役立ちますか?


8
ここには良い答えがたくさんあるので、「パイルが十分に大きくないとき」と呼びます。
Don Werve

回答:


119

最大(または最小)の項目にすばやくアクセスする必要がある場合は常に使用してください。その項目は常に配列の最初の要素またはツリーのルートになるためです。

ただし、配列の残りの部分は部分的に並べ替えられていません。したがって、即時アクセスは最大(最小)のアイテムにのみ可能です。挿入は高速であるため、着信イベントまたはデータを処理し、常に最も早い/最大のイベントにアクセスできる優れた方法です。

優先キュー、スケジューラー(最初のアイテムが必要な場合)などに役立ちます。

ヒープは、親ノードの値がその子孫ノードの値よりも大きいツリーです。

ヒープを、ルートノードを最初に(次にそのノードの子を次に、次にそれらのノードの子を次に)深さの線形順に格納されたバイナリツリーと考える場合、次に、インデックスNのノードの子は2N + 1と2N + 2にあります。このプロパティにより、インデックスによる迅速なアクセスが可能になります。ヒープはノードを交換することによって操作されるため、これによりインプレースソートが可能になります。


3
また、追加の配列割り当てを必要としない便利な保証付きNlogNソートである可能性があることに注意してください
オーバーフロー

37
インタビューの質問の山を知るのも素晴らしいことです;)
vivekian2 2014年

19
@ vivekian2私がここにいる唯一の理由は、私がインタビューをしようとしているからです。
byxor 2016年

最大(または最小)の項目を追跡するために、補助スタックを持つスタッククラスを使用しないでください。検索はO(1)
Ridhwaan Shakeel

@RidhwaanShakeelスタックを使用する場合、アイテムは常に頭に配置されます。アイテムの位置が最大のイベントなどのアイテムのプロパティに基づいて決定される必要がある場合(イベントに参加した人数に基づく)。
SandeepGodara

48

ヒープは、最小値または最大値にすばやくアクセスできるようにするための構造です。

しかし、なぜそれが必要なのでしょうか。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つのヒープに他の要素よりも多くの要素がある)、最大のヒープから要素を引き出し、最小の要素に追加します。今ではバランスが取れています。


4
より洗練された例は素晴らしいです!私は間違いなくいつかこれを試すつもりです。しかし、あなたの例には小さな間違いがあると思います。中央の2つの要素を平均して中央値を取得する必要があるためです。現在の中央値より大きい数値を格納するには最小ヒープを、現在の中央値より小さい数値を格納するには最大ヒープを使用する必要があると思います。このようにして、中央の2つの要素を一定の時間で抽出し、中央値を計算できますか?私は正しいですか?
Calvin Ku

12

ヒープの特徴は、データが半順序に維持される構造であることです。したがって、これは完全な順序を維持するコストとランダムなカオスを検索するコストとの間の適切なトレードオフです。その特性は、選択、順序付け、分類などの多くのアルゴリズムで使用されます。

ヒープのもう1つの便利な特性は、配列からインプレースで作成できることです。


3

選択アルゴリズムにも適しています(最小または最大の検索)


3

一時リストをソートするときはいつでも、ヒープを検討する必要があります。


0

最小要素と最大要素にそれぞれアクセスする場合は、minHeapまたはmaxHeapを使用できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.