web-dev-qa-db-ja.com

make_heapのポイントは何ですか?

誰かがstd::make_heapのようなSTLヒープ関数テンプレートのポイントを教えてもらえますか?なぜ誰もがそれらを使用するのでしょうか?実用はありますか?

46
rlbond

リストから priority queue を作成する場合は、make_heapを使用できます。

内部的には、ヒープは、各ノードが自身の値以下の値にリンクするツリーです。 make_heapによって生成されたヒープでは、メモリ消費リンクによって決定されるのではなく、ツリー内の要素の特定の位置は、シーケンス内のその絶対位置によって決定されます。* firstは常にヒープ内の最高値です。

ヒープでは、ヒーププロパティを保持する関数Push_heapおよびpop_heapを使用して、対数時間で要素を追加または削除できます。

21
akappa

あなたの直接的な質問は、アルゴリズムとデータ構造のクラスによって適切に回答されます。ヒープは、コンピュータサイエンスのアルゴリズムの至る所で使用されています。以下にリンクされているmake_heap関数から引用すると、「ヒープは、各ノードが自身の値以下の値にリンクしているツリーです。」ヒープには多くのアプリケーションがありますが、私が最も頻繁に使用するのは、N値のソートされたリストを効率的に追跡したい場合の検索の問題です。

STLヒープ関数に初めて遭遇したとき、私はあなたと同じように混乱しました。私の質問は少し異なりましたが。 「STD :: vectorと同じデータ構造のクラスにSTLヒープがないのはなぜですか?」私はそれがこのように機能するはずだと思いました:

std::heap< int > my_heap;
my_heap.heap_insert( 7 );
my_heap.heap_insert( 3 );

ただし、STLヒープ関数の背後にある考え方は、std :: vectorを含むいくつかの異なる基本的なSTLコンテナーからヒープデータ構造を作成できることです。これは、プログラムの他の場所で使用するためにコンテナーを渡したい場合に非常に役立ちます。 std :: vector以外のものを使用することを選択した場合、ヒープの基になるコンテナーを選択できるため、これも少しいいです。本当に必要なのは次のものだけです。

template <class RandomAccessIterator>
  void make_heap ( RandomAccessIterator first, RandomAccessIterator last );

これは、多くの異なるコンテナーをヒープに作成できることを意味します。メソッドシグネチャではコンパレーターもオプションです。make_heap関数のSTLページで試すことができるさまざまなことの詳細を読むことができます。

リンク:

43
James Thompson

_std::make_heap_は、実際にはほとんど使用しないでください。ヒープが優先キューに役立つことは事実ですが、構造を手動で維持する必要がある理由は説明されていません。 _std::priority_queue_には、優先キューだけが必要な場合に、はるかに便利なインターフェースがあります。

_make_heap_とその兄弟を直接使用する場合は、基礎となるコンテナーに変更を加えるたびに必ずそれらを使用する必要があります。私はそれらが2回または3回使用され、毎回が誤って使用されたことを確認しました。

しばらくの間、優先キューとしてベクターを使用してから並べ替える必要があったので、私は自分自身で直接ヒープ操作を使用しただけでした。 _std::make_heap_が必要になることはほとんどありません。

要素を変更する機能を持つ優先キューが必要な場合は、_std::set_を使用できます。 *s.begin()または*s.rbegin()を使用して最小または最大の要素をそれぞれ取得し、古い値を削除して新しい値を挿入することで要素を更新できます。

8
Jørgen Fogh

std::make_heap()std::Push_heap()およびstd::pop_heap()とともに使用して、ベクトルまたは配列の上にバイナリヒープを維持することになっています。後者の2つの関数は、ヒープを不変に維持します。 std::heap_sort()を使用して、このようなヒープをソートすることもできます。プライオリティキューに_std::priority_queue_を使用できることは事実ですが、内部で取得することはできません。また、std::make_heap()std::heap_sort()を一緒に使用すると、C++でヒープソートを実行する非常に簡単な方法になります。

8
newacct

[バイナリ]ヒープを作成するには、基本的に2つの方法があります。空のヒープを作成し、各要素を一度に1つずつ挿入するか、値の範囲を取得してそれらをヒープ化します。

ヒープの各プッシュ操作にはO(logn)時間かかるため、N個のアイテムをヒープにプッシュする場合、O(NlogN)時間かかります。ただし、値の配列からバイナリヒープを構築するには、O(N)時間しかかかりません。

したがって、各要素を配列(またはランダムアクセス反復子をサポートする他のコンテナー)に挿入し、挿入時にヒープ構造を維持するよりも、配列に対してmake_heap()を呼び出す方が理にかなっています。

5
Niki Yoshiuchi

上記に加えて、STLのソートアルゴリズムは introsort です。これは、クイックソートとヒープソートの混合です(前者のパフォーマンスが悪い場合、クイックソートからヒープソートにフェイルオーバーします)。 make_heapは、introsortに必要なheapsortの実行に必要なヒープ構造を作成します。

4
Todd Gardner

ヒープデータ構造 を構築および維持するために使用されます。

2
anon