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

C++のsetとmultisetの違いとは?特徴と使い分けを実例付きで解説

C++には、データを効率的に格納・検索するための連想コンテナとして「set」と「multiset」が用意されています。どちらも標準テンプレートライブラリ(STL)に属するコンテナであり、要素への高速なアクセスや挿入を可能にするデータ構造です。

しかし、両者には重複要素の扱いをはじめとする重要な違いがあります。本記事では、setとmultisetの相違点を比較表で整理し、実際のコード例と実行結果を通じて、それぞれの動作の違いをわかりやすく解説します。

setとmultisetの主な違い

項目setmultiset
定義連想コンテナの一種で、キーと値のペアを格納します。各要素の値がそのまま識別子となるため、すべての要素は一意である必要があります。C++ STLに含まれる連想コンテナの一種で、setと同様にソート済みのキーと値のペアを格納します。ただし、setと異なり重複したキーを持つことができます
ソートデータは常にソートされた順序で格納されます。こちらも同様に、データはソートされた順序で格納されます。
重複値重複した値を格納することはできません。同じ値を挿入しようとしても無視されます。重複した値を複数個格納することができます。
要素の変更一度挿入した要素の値を直接変更することはできません。変更したい場合は、削除してから再度挿入する必要があります。こちらも同様に、挿入後の要素の値を直接変更することはできません。

両者の最も大きな違いは重複値を許可するかどうかという点です。それ以外の基本的な性質(自動ソート、要素の変更不可など)は共通しています。

サンプルコードで確認するsetの動作

まずはsetの例です。15個の整数(重複あり)を挿入してみます。

#include <iostream>
#include <set>
using namespace std;

int main() {
    int data[15] = {11, 55, 22, 66, 33, 22, 11, 44, 77, 88, 66, 99, 66, 23, 41};
    set<int> my_set;

    for (int i = 0; i < 15; i++) {
        my_set.insert(data[i]);
    }

    set<int>::iterator it;
    for (it = my_set.begin(); it != my_set.end(); it++) {
        cout << "Item: " << *it << endl;
    }
}

実行結果

Item: 11
Item: 22
Item: 23
Item: 33
Item: 41
Item: 44
Item: 55
Item: 66
Item: 77
Item: 88
Item: 99

入力データには「11」「22」「66」などの重複が含まれていましたが、出力を見ると各値が1回だけ表示され、昇順に並んでいることがわかります。これがsetの特徴です。重複要素は自動的に排除され、常に整列された状態が保たれます。

サンプルコードで確認するmultisetの動作

次に、まったく同じデータをmultisetに挿入してみます。

#include <iostream>
#include <set>
using namespace std;

int main() {
    int data[15] = {11, 55, 22, 66, 33, 22, 11, 44, 77, 88, 66, 99, 66, 23, 41};
    multiset<int> my_set;

    for (int i = 0; i < 15; i++) {
        my_set.insert(data[i]);
    }

    multiset<int>::iterator it;
    for (it = my_set.begin(); it != my_set.end(); it++) {
        cout << "Item: " << *it << endl;
    }
}

実行結果

Item: 11
Item: 11
Item: 22
Item: 22
Item: 23
Item: 33
Item: 41
Item: 44
Item: 55
Item: 66
Item: 66
Item: 66
Item: 77
Item: 88
Item: 99

今度の出力では、「11」「22」「66」などの値が入力データに含まれていた回数だけ繰り返し表示されています。multisetは重複を許可しながら、setと同様に昇順ソートを維持するコンテナだからです。

まとめ:setとmultisetの使い分け

  • set:重複のない一意な値の集合を管理したい場合に適しています。存在判定やユニークな要素の列挙に便利です。
  • multiset:同じ値が複数回現れる可能性のあるデータを、ソート状態で管理したい場合に適しています。度数分布の管理などにも活用できます。

どちらも内部では平衡二分探索木(赤黒木)によって実装されており、挿入・削除・検索をO(log n)の計算量で行えるという利点があります。用途に応じて適切に使い分けることで、効率的なプログラムを書くことができます。

  1. C++の文字リテラルと文字列リテラルの違いをわかりやすく解説

    C++における文字リテラルと文字列リテラルの基本C++では、シングルクォート( )で囲まれた1文字は「文字リテラル」として扱われ、その型は char になります。例えば a は char 型であり、ASCIIベースのシステムでは整数値 97 を持ちます。一方、ダブルクォート( )で囲まれた1文字または複数文字の並びは「文字列リテラル」として扱われます。その型は const char[] であり、実体は「文字列の長さ + 1」のサイズを持つ配列です。この余分な1文字分は、文字列の終端を示すヌル文字(\0)として確保されています。具体的な違いのポイント文字リテラル: 原則として1文字のみを格納する

  2. JavaにおけるListとSetの違いを徹底解説

    ListとSetは、どちらもJavaのCollectionフレームワークに属するインターフェースであり、双方ともCollectionインターフェースを継承しています。これらは、複数のオブジェクトをひとつのまとまった単位として格納・管理するために使用されます。JDK 1.2以前のJavaでは、オブジェクトをグループ化するために配列(Array)、Vector、Hashtableなどが利用されていました。JDK 1.2でCollectionフレームワークが導入されて以降、ListやSetといったインターフェースがオブジェクト管理の標準的な手段となっています。本記事では、ListとSetの主な違いを