Python
 Computer >> コンピューター >  >> プログラミング >> Python

C++ STLのヒープ操作徹底解説:make_heap・push_heap・pop_heap・sort_heap・is_heapの使い方

C++ STLには、ヒープ(heap)データ構造を扱うための便利な関数群が用意されています。ヒープを利用すると要素を高速に挿入でき、取り出し操作では常に残りの要素の中で最大の値が得られます。最大値以外の要素の並び順は実装に依存します。本記事では、STLが提供する主要なヒープ操作関数を、サンプルコードと実行結果とともにわかりやすく解説します。

make_heap() ― 範囲をヒープ化する

make_heap() は、コンテナ内の指定した範囲をヒープ構造に変換する関数です。また、front() を使うことで、ヒープの先頭要素(最大値)を参照できます。

サンプルコード

#include <bits/stdc++.h>
using namespace std;

int main() {
    vector<int> heap = {33, 43, 53, 38, 28};
    make_heap(heap.begin(), heap.end());
    cout << "Top element is : " << heap.front() << endl;
}

実行結果

Top element is : 53

push_heap() と pop_heap() ― 要素の挿入と削除

push_heap() は、新しい要素をコンテナに追加した後(push_back後)に呼び出すことで、ヒープの性質を保ったまま再構成します。ヒープのサイズは1増加し、新しく追加された要素は適切な位置へ自動的に配置されます。

pop_heap() は、ヒープの最大要素を末尾へ移動した後(pop_back前)に呼び出すことで、残りの要素を再度ヒープ化します。ヒープのサイズは1減少し、削除後もヒープの性質が維持されます。

サンプルコード

#include <bits/stdc++.h>
using namespace std;

int main() {
    vector<int> heap = {33, 43, 53, 38, 28};
    make_heap(heap.begin(), heap.end());
    cout << "Top element is : " << heap.front() << endl;

    // 要素を挿入してヒープを再構成
    heap.push_back(60);
    push_heap(heap.begin(), heap.end());
    cout << "Top element after insert : " << heap.front() << endl;

    // 最大要素を削除してヒープを再構成
    pop_heap(heap.begin(), heap.end());
    heap.pop_back();
    cout << "Top element after deletion : " << heap.front() << endl;
}

実行結果

Top element is : 53
Top element after insert : 60
Top element after deletion : 53

sort_heap() ― ヒープソートによる昇順ソート

sort_heap() は、ヒープソートの手法を用いて、ヒープ内の要素を昇順に並べ替える関数です。ソート後の範囲はもはやヒープではなくなる点に注意してください。

サンプルコード

#include <bits/stdc++.h>
using namespace std;

int main() {
    vector<int> heap = {33, 43, 53, 38, 28};
    make_heap(heap.begin(), heap.end());

    cout << "Before Sort : ";
    for (const auto &i : heap) {
        cout << i << ' ';
    }

    sort_heap(heap.begin(), heap.end());

    cout << "\nAfter Sort : ";
    for (const auto &i : heap) {
        cout << i << ' ';
    }
}

実行結果

Before Sort : 53 43 33 38 28
After Sort : 28 33 38 43 53

is_heap() と is_heap_until() ― ヒープの判定

is_heap() は、指定した範囲がヒープとして成立しているかどうかを判定します。範囲がヒープであれば true を、そうでなければ false を返します。多くの実装では、降順にソートされたコンテナもヒープとして扱われます。

is_heap_until() は、範囲の先頭からどこまでがヒープとして成立しているかを調べ、その境界位置を指すイテレータを返します。

サンプルコード

#include <bits/stdc++.h>
using namespace std;

int main() {
    vector<int> heap = {33, 43, 53, 38, 28};

    // ヒープ化前の判定
    if (is_heap(heap.begin(), heap.end()))
        cout << "This is a heap" << endl;
    else
        cout << "This is not a heap" << endl;

    // ヒープ化
    make_heap(heap.begin(), heap.end());

    // ヒープ化後の判定
    if (is_heap(heap.begin(), heap.end()))
        cout << "This is a heap" << endl;
    else
        cout << "This is not a heap" << endl;

    // ヒープとして成立している範囲の終端を取得
    auto iter2 = is_heap_until(heap.begin(), heap.end());
    cout << "The heap elements are : ";
    for (auto iter = heap.begin(); iter != iter2; ++iter)
        cout << *iter << " ";
}

実行結果

This is not a heap
This is a heap
The heap elements are : 53 43 33 38 28

まとめ

C++ STLのヒープ関連関数を使いこなせば、優先度付きキューのような「常に最大値へ高速アクセスしたい」場面を効率的に実装できます。make_heap で範囲をヒープ化し、push_heappop_heap で挿入・削除を管理し、sort_heap で整列、is_heapis_heap_until で状態検証という流れを押さえておきましょう。

  1. C++ STLのスタック(stack)徹底解説!LIFO構造の基本操作とサンプルコード

    C++ STLにおけるスタック(stack)は、LIFO(Last In First Out:後入れ先出し)構造として実装されるコンテナです。LIFOとは「最後に入れたものが最初に取り出される」という意味で、本を一冊ずつ積み上げた山をイメージすると理解しやすいでしょう。一番上に置いた本(=最後に挿入された要素)が最初に取り出されることから、この構造はLIFOと呼ばれています。 スタックで使える主な操作 1. top() – 最上位要素の取得 スタックの最上位(先頭)にある要素への参照を返します。要素自体は削除されません。 構文:name_of_stack.top() 引数:なし 戻り値:ス

  2. C++で学ぶ二項ヒープ(Binomial Heap)の基礎と操作

    二項ヒープ(Binomial Heap)とは、二分ヒープ(Binary Heap)を拡張したデータ構造です。二分ヒープが提供する各種操作に加えて、より高速なマージ(union)操作を実現できる点が大きな特徴です。二項ヒープは、複数の二項木(Binomial Tree)のコレクションとして表現されます。二項木(Binomial Tree)とは?次数kの二項木は、次数k-1の二項木を2つ用意し、一方をもう一方の最左の子として連結することで構築できます。次数kの二項木には、以下のような性質があります。ノードの総数は正確に2k個である。木の深さはkである。深さi(i = 0, 1, ..., k)には