C++におけるsetとunordered_setの違いを徹底解説!特徴と使い分けのポイント
はじめに
C++のsetとunordered_setは、どちらもデータを効率的に格納・検索・挿入するための連想コンテナ(データ構造)です。しかし、内部実装やデータの保持方法に大きな違いがあり、用途に応じた使い分けが重要になります。
本記事では、setとunordered_setの主な違いを比較表で整理し、実際のコード例を通じてそれぞれの動作の違いを確認します。
setとunordered_setの主な違い
| 項目 | set | unordered_set |
|---|---|---|
| 定義 | キーと値のペアでデータを格納する連想コンテナの一種。要素の値そのものがキーとして機能するため、すべての要素は一意である必要があります。 | C++ STL(標準テンプレートライブラリ)の一部で、setと同様の連想コンテナですが、データをソートせずに格納する点が異なります。 |
| ソート | データは常にソートされた順序で保持されます。 | データはソートされず、ハッシュ値に基づいた順序で格納されます。 |
| 重複値 | 重複した値は格納できません。 | 重複した値は挿入時に破棄(無視)されます。 |
| 内部実装 | 二分探索木(赤黒木)で実装されています。 | ハッシュテーブルで実装されています。 |
setの使用例
#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;
}
return 0;
}
実行結果
Item: 11
Item: 22
Item: 23
Item: 33
Item: 41
Item: 44
Item: 55
Item: 66
Item: 77
Item: 88
Item: 99
setでは重複した値が自動的に除去され、昇順にソートされた状態で出力されていることがわかります。
unordered_setの使用例
#include <iostream>
#include <unordered_set>
using namespace std;
int main() {
int data[15] = {11, 55, 22, 66, 33, 22, 11, 44, 77, 88, 66, 99, 66, 23, 41};
unordered_set<int> my_set;
for (int i = 0; i < 15; i++) {
my_set.insert(data[i]);
}
unordered_set<int>::iterator it;
for (it = my_set.begin(); it != my_set.end(); it++) {
cout << "Item: " << *it << endl;
}
return 0;
}
実行結果
Item: 11
Item: 55
Item: 22
Item: 66
Item: 33
Item: 44
Item: 77
Item: 88
Item: 99
Item: 23
Item: 41
unordered_setでも重複は除去されますが、ソートは行われず、ハッシュテーブルの内部構造に依存した順序で出力されます。なお、この順序は実行環境や実装によって異なる場合があります。
まとめ
要素を常にソートされた順序で扱いたい場合や、順序付きの走査が必要な場合はsetが適しています。一方、要素の順序が不要で、平均O(1)の高速な検索・挿入を求める場合はunordered_setを選ぶとよいでしょう。用途に応じて両者を適切に使い分けることで、プログラムの効率を大きく向上させることができます。
-
C++の文字リテラルと文字列リテラルの違いをわかりやすく解説
C++における文字リテラルと文字列リテラルの基本C++では、シングルクォート( )で囲まれた1文字は「文字リテラル」として扱われ、その型は char になります。例えば a は char 型であり、ASCIIベースのシステムでは整数値 97 を持ちます。一方、ダブルクォート( )で囲まれた1文字または複数文字の並びは「文字列リテラル」として扱われます。その型は const char[] であり、実体は「文字列の長さ + 1」のサイズを持つ配列です。この余分な1文字分は、文字列の終端を示すヌル文字(\0)として確保されています。具体的な違いのポイント文字リテラル: 原則として1文字のみを格納する
-
JavaにおけるListとSetの違いを徹底解説
ListとSetは、どちらもJavaのCollectionフレームワークに属するインターフェースであり、双方ともCollectionインターフェースを継承しています。これらは、複数のオブジェクトをひとつのまとまった単位として格納・管理するために使用されます。JDK 1.2以前のJavaでは、オブジェクトをグループ化するために配列(Array)、Vector、Hashtableなどが利用されていました。JDK 1.2でCollectionフレームワークが導入されて以降、ListやSetといったインターフェースがオブジェクト管理の標準的な手段となっています。本記事では、ListとSetの主な違いを