【C++】STL setの要素の挿入(insert)と削除(erase)をサンプルコードで解説
はじめに
この記事では、C++のSTL(標準テンプレートライブラリ)における「set」コンテナへの要素の挿入と削除の方法を、サンプルコードと実行結果とともに解説します。
setは連想コンテナの一種で、最大の特徴は「重複する要素を格納できない」ことと「要素が常にソートされた順序で保持される」ことです。この性質により、重複排除や整列済みデータの管理を簡単かつ効率的に行うことができます。
setコンテナの主な特徴
- 重複不可: 同じ値の要素は1つしか保持されません。
- 自動ソート: 要素を挿入すると、常に昇順に並び替えられます。
- 高速な操作: 内部は平衡二分探索木(赤黒木)で実装されており、挿入・削除・検索はいずれもO(log n)の計算量で実行できます。
要素の挿入(insert)
setへの挿入には、主に以下の3つの形式があります。
- insert(値): 単一の要素を挿入します。戻り値は pair<iterator, bool> で、boolがtrueなら新規挿入、falseなら既に存在していたことを示します。
- insert(イテレータ, 値): 挿入位置のヒントを指定して挿入します(実際の格納位置はソート順に従います)。
- insert(先頭, 末尾): 配列などの範囲内の要素をまとめて挿入します。
サンプルコード
#include<iostream>
#include<set>
using namespace std;
int main(){
set<int> st;
// イテレータの宣言
set<int>::iterator it = st.begin();
set<int>::iterator it1, it2;
pair< set<int>::iterator,bool> ptr;
// 単一要素の挿入
ptr = st.insert(20);
if (ptr.second)
cout << "The element was newly inserted" ;
else cout << "The element was already present" ;
cout << "\nThe set elements after 1st insertion are : ";
for (it1 = st.begin(); it1!=st.end(); ++it1)
cout << *it1 << " ";
st.insert(it, 24);
cout << "\nThe set elements after 2nd insertion are : ";
for (it1 = st.begin(); it1!=st.end(); ++it1)
cout << *it1 << " ";
int arr[3] = { 25, 24, 26 };
st.insert(arr, arr+3);
cout << "\nThe set elements after 3rd insertion are : ";
for (it1 = st.begin(); it1!=st.end(); ++it1)
cout << *it1 << " ";
}実行結果
The element was newly inserted The set elements after 1st insertion are : 20 The set elements after 2nd insertion are : 20 24 The set elements after 3rd insertion are : 20 24 25 26
1回目の挿入では戻り値のboolを利用して、要素が新しく追加されたのか、それとも既に存在していたのかを判定しています。3回目の挿入では配列{25, 24, 26}を渡していますが、24はすでに存在するため重複して登録されず、最終的にsetには20・24・25・26の4要素のみが格納されます。
要素の削除(erase)
setからの削除にも、主に以下の3つの形式があります。
- erase(イテレータ): イテレータが指す要素を1つ削除します。
- erase(値): 指定した値と一致する要素を削除します。
- erase(先頭, 末尾): 指定した範囲の要素をまとめて削除します。
サンプルコード
#include<iostream>
#include<set>
using namespace std;
int main(){
set<int> st;
// イテレータの宣言
set<int>::iterator it;
set<int>::iterator it1;
set<int>::iterator it2;
pair< set<int>::iterator,bool> ptr;
// setへ値を挿入
for (int i=1; i<10; i++)
st.insert(i*5);
cout << "The set elements after insertion are : ";
for (it1 = st.begin(); it1!=st.end(); ++it1)
cout << *it1 << " ";
it = st.begin();
cout << endl;
++it;
st.erase(it);
// 削除後のset要素を表示
cout << "The set elements after 1st deletion are : ";
for (it1 = st.begin(); it1!=st.end(); ++it1)
cout << *it1 << " ";
st.erase(40);
cout << "\nThe set elements after 2nd deletion are : ";
for (it1 = st.begin(); it1!=st.end(); ++it1)
cout << *it1 << " ";
++it;
++it;
++it;
++it;
st.erase(it, st.end());
cout << "\nThe set elements after 3rd deletion are : ";
for (it1 = st.begin(); it1!=st.end(); ++it1)
cout << *it1 << " ";
cout << endl;
}実行結果
The set elements after insertion are : 5 10 15 20 25 30 35 40 45 The set elements after 1st deletion are : 5 15 20 25 30 35 40 45 The set elements after 2nd deletion are : 5 15 20 25 30 35 45 The set elements after 3rd deletion are : 5 15 20
この例では、まず5から45まで5刻みの9個の要素を挿入しています。1回目の削除ではイテレータを使って10を、2回目では値を直接指定して40を削除し、3回目では範囲指定によって25以降の要素をすべて削除しています。
注意: erase()で削除された要素を指すイテレータは無効になるため、削除後にそのイテレータを再利用する際は細心の注意が必要です。実務では、削除後は必要に応じてbegin()やend()からイテレータを取得し直すのが安全です。
まとめ
setは「重複を許さない」「自動的にソートされる」という特徴を持つ、非常に便利なコンテナです。insert()による単一・ヒント付き・範囲の3種類の挿入と、erase()によるイテレータ・値・範囲の3種類の削除を使い分けることで、整列済みのユニークなデータ集合を効率的に管理できます。
-
C++のSTLでset_intersectionを実装し、2つの集合の積集合を求める方法
2つの集合の積集合(インターセクション)とは、両方の集合に共通して含まれる要素だけを集めたものです。set_intersection関数によってコピーされる要素は、必ず最初の集合から取り出され、元の順序がそのまま維持されます。また、この関数を正しく動作させるためには、処理前に両方の集合がそれぞれソート済みである必要があります。 集合に対する代表的な操作には、以下のようなものがあります。 和集合(ユニオン) 積集合(インターセクション) 対称差(排他的論理和・XOR) 差集合(減算) アルゴリズム Begin 結果を格納するvector型変数vとイテレータstを宣言する。 st =
-
【C++】STLのset_differenceを使って2つの集合の差分を求める方法
2つの集合の「差(差集合)」とは、1つ目の集合には存在するが、2つ目の集合には存在しない要素だけから構成される集合のことです。set_difference関数によってコピーされる要素は、必ず1つ目の集合から取り出され、元の順序が保たれます。また、この関数を正しく動作させるためには、両方の集合があらかじめソート(整列)されている必要があります。代表的な集合演算には以下のようなものがあります。和集合(Union)積集合(Intersection)対称差(Symmetric Difference / 排他的論理和)差集合(Difference / 減算)アルゴリズムBegin 集合用のvec