C++のSTL set(セット)における要素の挿入と削除の基本
C++のSTL(標準テンプレートライブラリ)に含まれる set コンテナは、重複しない要素を自動的にソートして管理する便利なデータ構造です。本記事では、setへの挿入と削除の方法を、実際に動作するサンプルコードと出力例とともに詳しく解説します。
要素の挿入:insert()
STLのsetに要素を挿入するには、insert() 関数を使用します。insert() はオブジェクトへの参照を受け取り、その要素を適切な位置(自動的にソートされた状態を保つ位置)に追加します。
すでに同じ値がセット内に存在する場合、重複した挿入は行われず、セットの内容は変化しません。これがsetコンテナの大きな特徴です。
使用する主な関数
st.size()… セットの現在の要素数(サイズ)を返します。st.insert()… セットに新しい要素を挿入します。
サンプルコード
#include <iostream>
#include <set>
#include <string>
#include <cstdlib>
using namespace std;
int main() {
set<int> st;
set<int>::iterator it;
int c, i;
while (1) {
cout<<"1.セットのサイズを表示"<<endl;
cout<<"2.セットに要素を挿入"<<endl;
cout<<"3.セットの中身を表示: "<<endl;
cout<<"4.終了"<<endl;
cout<<"選択してください: ";
cin>>c;
switch(c) {
case 1:
cout<<"セットのサイズ: ";
cout<<st.size()<<endl;
break;
case 2:
cout<<"挿入する値を入力: ";
cin>>i;
st.insert(i);
break;
case 3:
cout<<"イテレータによるセットの表示: ";
for (it = st.begin(); it != st.end(); it++) {
cout << (*it)<<" ";
}
cout<<endl;
break;
case 4:
exit(1);
break;
default:
cout<<"無効な選択です"<<endl;
}
}
return 0;
}
実行結果
1.セットのサイズを表示 2.セットに要素を挿入 3.セットの中身を表示: 4.終了 選択してください: 1 セットのサイズ: 0 1.セットのサイズを表示 2.セットに要素を挿入 3.セットの中身を表示: 4.終了 選択してください: 2 挿入する値を入力: 4 1.セットのサイズを表示 2.セットに要素を挿入 3.セットの中身を表示: 4.終了 選択してください: 2 挿入する値を入力: 6 1.セットのサイズを表示 2.セットに要素を挿入 3.セットの中身を表示: 4.終了 選択してください: 2 挿入する値を入力: 8 1.セットのサイズを表示 2.セットに要素を挿入 3.セットの中身を表示: 4.終了 選択してください: 2 挿入する値を入力: 10 1.セットのサイズを表示 2.セットに要素を挿入 3.セットの中身を表示: 4.終了 選択してください: 3 イテレータによるセットの表示: 4 6 8 10 1.セットのサイズを表示 2.セットに要素を挿入 3.セットの中身を表示: 4.終了 選択してください: 4 終了コード: 1
出力結果を見ると、挿入した順序に関係なく、要素が常に昇順(4 → 6 → 8 → 10)に並んでいることが確認できます。これはsetが内部で自動的にソートを行うためです。
効率的な挿入:emplace()
emplace() も要素をセットに挿入するための関数ですが、insert() とは動作が異なります。emplace() はオブジェクトをその場で直接構築(in-place構築)するため、不要な一時オブジェクトのコピーが発生しません。その結果、特に大型のオブジェクトを扱う場合に、insert() よりも効率よく挿入できます。
使用する主な関数
st.size()… セットの現在の要素数を返します。st.emplace()… オブジェクトを直接構築しながらセットに挿入します。
サンプルコード
#include <iostream>
#include <set>
#include <string>
#include <cstdlib>
using namespace std;
int main() {
set<int> st;
set<int>::iterator it;
int c, i;
while (1) {
cout<<"1.セットのサイズを表示"<<endl;
cout<<"2.セットに要素を挿入"<<endl;
cout<<"3.セットの中身を表示: "<<endl;
cout<<"4.終了"<<endl;
cout<<"選択してください: ";
cin>>c;
switch(c) {
case 1:
cout<<"セットのサイズ: ";
cout<<st.size()<<endl;
break;
case 2:
cout<<"挿入する値を入力: ";
cin>>i;
st.emplace(i);
break;
case 3:
cout<<"イテレータによるセットの表示: ";
for (it = st.begin(); it != st.end(); it++) {
cout << (*it)<<" ";
}
cout<<endl;
break;
case 4:
exit(1);
break;
default:
cout<<"無効な選択です"<<endl;
}
}
return 0;
}
実行結果
1.セットのサイズを表示 2.セットに要素を挿入 3.セットの中身を表示: 4.終了 選択してください: 1 セットのサイズ: 0 1.セットのサイズを表示 2.セットに要素を挿入 3.セットの中身を表示: 4.終了 選択してください: 2 挿入する値を入力: 4 1.セットのサイズを表示 2.セットに要素を挿入 3.セットの中身を表示: 4.終了 選択してください: 6 無効な選択です 1.セットのサイズを表示 2.セットに要素を挿入 3.セットの中身を表示: 4.終了 選択してください: 2 挿入する値を入力: 6 1.セットのサイズを表示 2.セットに要素を挿入 3.セットの中身を表示: 4.終了 選択してください: 2 挿入する値を入力: 7 1.セットのサイズを表示 2.セットに要素を挿入 3.セットの中身を表示: 4.終了 選択してください: 2 挿入する値を入力: 8 1.セットのサイズを表示 2.セットに要素を挿入 3.セットの中身を表示: 4.終了 選択してください: 3 イテレータによるセットの表示: 4 6 7 8 1.セットのサイズを表示 2.セットに要素を挿入 3.セットの中身を表示: 4.終了 選択してください: 4 終了コード: 1
この実行例では、存在しないメニュー番号「6」を選んだ際に「無効な選択です」と表示されるdefault処理の動作も確認できます。
要素の削除:erase()
セットから要素を削除するには、erase() 関数を使用します。erase() の引数には、次のいずれかを指定できます。
- 値 … 指定した値と一致する要素を削除します。
- 位置(イテレータ) … 指定した位置にある要素を削除します。
- 範囲(イテレータのペア) … 指定した範囲内のすべての要素をまとめて削除します。
使用する主な関数
st.size()… セットの現在の要素数を返します。st.insert()… セットに要素を挿入します。st.erase()… セットから要素を削除します。
サンプルコード
#include <iostream>
#include <set>
#include <string>
#include <cstdlib>
using namespace std;
int main() {
set<int> st;
set<int>::iterator it;
int c, i;
while (1) {
cout<<"1.セットのサイズを表示"<<endl;
cout<<"2.セットに要素を挿入"<<endl;
cout<<"3.セットから要素を削除"<<endl;
cout<<"4.セットの中身を表示: "<<endl;
cout<<"5.終了"<<endl;
cout<<"選択してください: ";
cin>>c;
switch(c) {
case 1:
cout<<"セットのサイズ: ";
cout<<st.size()<<endl;
break;
case 2:
cout<<"挿入する値を入力: ";
cin>>i;
st.insert(i);
break;
case 3:
cout<<"削除する要素を入力: ";
cin>>i;
st.erase(i);
break;
case 4:
cout<<"イテレータによるセットの表示: ";
for (it = st.begin(); it != st.end(); it++) {
cout << (*it)<<" ";
}
cout<<endl;
break;
case 5:
exit(1);
break;
default:
cout<<"無効な選択です"<<endl;
}
}
return 0;
}
実行結果
1.セットのサイズを表示 2.セットに要素を挿入 3.セットから要素を削除 4.セットの中身を表示: 5.終了 選択してください: 1 セットのサイズ: 0 1.セットのサイズを表示 2.セットに要素を挿入 3.セットから要素を削除 4.セットの中身を表示: 5.終了 選択してください: 2 挿入する値を入力: 1 1.セットのサイズを表示 2.セットに要素を挿入 3.セットから要素を削除 4.セットの中身を表示: 5.終了 選択してください: 2 挿入する値を入力: 2 1.セットのサイズを表示 2.セットに要素を挿入 3.セットから要素を削除 4.セットの中身を表示: 5.終了 選択してください: 2 挿入する値を入力: 3 1.セットのサイズを表示 2.セットに要素を挿入 3.セットから要素を削除 4.セットの中身を表示: 5.終了 選択してください: 2 挿入する値を入力: 4 1.セットのサイズを表示 2.セットに要素を挿入 3.セットから要素を削除 4.セットの中身を表示: 5.終了 選択してください: 4 イテレータによるセットの表示: 1 2 3 4 1.セットのサイズを表示 2.セットに要素を挿入 3.セットから要素を削除 4.セットの中身を表示: 5.終了 選択してください: 3 削除する要素を入力: 2 1.セットのサイズを表示 2.セットに要素を挿入 3.セットから要素を削除 4.セットの中身を表示: 5.終了 選択してください: 4 イテレータによるセットの表示: 1 3 4 1.セットのサイズを表示 2.セットに要素を挿入 3.セットから要素を削除 4.セットの中身を表示: 5.終了 選択してください: 5 終了コード: 1
このように、値「2」を削除した後の表示では、残りの要素「1 3 4」だけが出力されており、erase() が正しく機能していることがわかります。
まとめ
insert()… セットに要素を挿入する基本的な関数。オブジェクトのコピーが発生します。emplace()… 要素をその場で直接構築して挿入するため、コピーのコストを抑えられます。erase()… 値・位置・範囲を指定して要素を削除できます。- setは重複を許さず、常に要素をソートされた状態で保持します。
これらの操作を使いこなせるようになると、重複チェックや順序付きデータ管理など、さまざまな場面でsetコンテナを効果的に活用できるようになります。ぜひ実際にコードを実行して、動作を確認してみてください。
-
C++ STLのsetコンテナでlower_bound()関数を使う方法
C++ STLのsetコンテナには、lower_bound()という便利なメンバ関数が用意されています。この関数は、引数として渡した値kと等しい要素を指すイテレータを返します。もしkがset内に存在しない場合は、「kより大きい要素のうち最小のもの」、つまり直後の要素を指すイテレータを返します。 setは内部的に要素を常にソート済みの状態で保持しているため、lower_bound()は二分探索によってO(log n)の計算量で効率的に動作します。 アルゴリズム Begin 空のsetコンテナsを初期化する。 lower boundの値を指すためのイテレータを宣言する。 s
-
C++ STLのset find()関数の使い方を解説
C++ STLのsetコンテナにおけるfind()関数は、指定した要素を検索し、その要素を指すイテレータを返します。もし要素がセット内に存在しない場合は、最後の要素の直後の位置(つまりend()が返すイテレータ)を指す値が返されます。この関数の計算量はO(log n)であり、setが内部的に平衡二分探索木(赤黒木)で実装されているため、高速な検索が可能です。アルゴリズムBegin セットコンテナの要素を出力するための関数 printS() を定義する。 空のセットコンテナ s を初期化し、いくつかの要素を挿入する。 関数を呼び出して、セットコンテナの要素を出力する。