C++のstd::setの使い方について詳しく解説

std::setは重複を許さず、要素を自動的にソートしてくれるコンテナです。
本記事では、初心者でもわかりやすくstd::setの基本的な使い方を、サンプルコードを用いて解説していきます。
std::setとは何か
std::setは、C++のSTL(Standard Template Library)に含まれるコンテナの一つです。
std::set
は、要素を自動的にソートし、重複する要素を持たない集合を作ることができます。
std::setは、二分探索木(Binary Search Tree)と呼ばれるデータ構造を用いて実装されています。
このため、要素の挿入や削除、検索などの操作が高速に行える特徴があります。
また、std::setはイテレータをサポートしており、範囲ベースのforループなどで簡単に要素を取り出すことができます。
std::setの基本的な使い方
要素の追加
std::setに要素を追加する場合は、insert()関数を使用します。以下は、int型の値を格納するstd::setに要素を追加する例です。
#include <iostream>
#include <set>
int main()
{
std::set<int> mySet;
// 要素の追加
mySet.insert(3);
mySet.insert(1);
mySet.insert(4);
return 0;
}
上記の例では、mySet
という名前のstd::set
変数を宣言し、insert()
関数で3, 1, 4
という値を順番に追加しています。
要素の取得
std::set
では、様々な方法で要素を取得することができます。
#include <iostream>
#include <set>
int main() {
std::set<int> myset = { 4, 2, 3, 1, 9, 5 };
// 最初の要素を取得する
auto it = myset.begin();
std::cout << "最初の要素: " << *it << '\n';
// 最後の要素を取得する
it = myset.end();
it--;
std::cout << "最後の要素: " << *it << '\n';
// 指定した値以上の最小の要素を取得する
it = myset.lower_bound(2);
std::cout << "2以上の数値の中で最小の値: " << *it << '\n';
// 指定した値より大きい最小の要素を取得する
it = myset.upper_bound(2);
std::cout << "2超過の数値の中で最小の値: " << *it << '\n';
for (auto it : myset) {
std::cout << it << " ";
}
}
最初の要素: 1
最後の要素: 9
2以上の数値の中で最小の値: 2
2超過の数値の中で最小の値: 3
1 2 3 4 5 9
様々な方法で要素を取得できますが、2番目の要素を取得したいからmySet[2]
のように書くというのはできないので注意してください(std::set
は配列ではありません)。
要素の削除
std::set
から要素を削除する場合は、erase()
関数を使用します。以下は、先ほど作成したmySetから値1
を削除する例です。
#include <iostream>
#include <set>
int main()
{
std::set<int> mySet;
// 要素の追加
mySet.insert(3);
mySet.insert(1);
mySet.insert(4);
// 要素の削除
mySet.erase(1);
for (auto it : myset) {
std::cout << it << " ";
}
return 0;
}
3 4
上記の例では、erase()
関数で値が1
の要素を削除しています。
要素の検索
std::setから特定の値が含まれているかどうか調べる場合は、find()
関数を使用します。
以下は、先ほど作成したmySet
から2
が含まれているかどうか調べる例です。
#include <iostream>
#include <set>
int main()
{
std::set<int> mySet;
// 要素の追加
mySet.insert(3);
mySet.insert(1);
mySet.insert(4);
// 値2が含まれているか調べる
if (mySet.find(2) != mySet.end()) {
std::cout << "2 is found." << std::endl;
} else {
std::cout << "2 is not found." << std::endl;
}
return 0;
}
2 is not found.
上記の例では、find()関数で値2が含まれているかどうか調べています。今回の場合だと2が含まれていないので、2 is not found.
と表示されます。
std::setの高度な使い方
イテレータの利用
std::setはイテレータをサポートしており、要素を順番に取り出すことができます。以下はイテレータを使用した例です。
#include <iostream>
#include <set>
int main() {
std::set<int> mySet = {1, 2, 3, 4, 5};
// イテレータを使用して全ての要素を表示する
for (auto itr = mySet.begin(); itr != mySet.end(); ++itr) {
std::cout << *itr << " ";
}
std::cout << std::endl;
return 0;
}
1 2 3 4 5
また、範囲ベースのfor文であれば以下のように書くことも可能です。
for (auto it : mySet) {
std::cout << it << " ";
}
先頭から終端まで順番にアクセスする場合はfor(auto it : mySet)
のような書き方がおすすめです。
要素の範囲検索
std::set
はlower_bound()
やupper_bound()
メソッドを提供しており、指定した値以上または以下の最初の要素を返します。以下はlower_bound()
メソッドを使用した例です。
#include <iostream>
#include <set>
int main() {
std::set<int> mySet = {1, 2, 3, 4, 5};
auto itr = mySet.lower_bound(3);
if (itr != mySet.end()) {
std::cout << "Found: " << *itr << std::endl;
} else {
std::cout << "Not found" << std::endl;
}
return 0;
}
Found: 3
要素の比較関数の指定
std:setではデフォルトでは昇順でソートされます。
ですが、降順に並び替えたい場合は、set変数を宣言する際にstd::greater<型名>
を第二引数に指定します。
その際に比較関数オブジェクト(ファンクタ)を渡すことで実現可能です。 以下は降順で並び替えた例です。
#include<iostream>
//↓これが必要なので注意
#include<functional>
#include<set>
using namespace std;
int main() {
multiset<int, std::greater<int>> mySet = { 3, 6, 4, 8, 1, 3 };
for (auto it : mySet) {
cout << it << " ";
}
return 0;
}
8 6 4 3 3 1
std::greater
はfunctional
をインクルードしないと使えない点にだけ注意しましょう。インクルードを忘れるとエラーになります。
終わりに
C++のstd::set
の基本的な使い方について、解説しました。
std::setは、要素の重複を許さず、自動的にソートされるため、データ管理に非常に便利です。
ぜひこの記事を参考にして、C++プログラミングのスキルアップに役立ててください。