set クラス

[機能]

  要素を自動的にソートして保持し,要素自身をキーとした探索が可能です.map と似ていますが,map ではキーとデータを別々に保持します.一般的に,二分木として実装されます.Comp に対しては,比較を行う二項関数オブジェクト名を指定します.指定しないと less (昇順)が選択されます.なお,以下に示す関数において,一般に,insert よりも,emplace を使ったほうが処理効率は良くなります.
template <class Key, class Comp = less<Key>,
class Allocator = allocator<Key>>
    class set		

[使用方法]
#include <set>
using namespace std;
set <Key> 変数名;
   set<int> x;   // 空の set,昇順
   set<int, greater<int>> x;   // 空の set,降順
   set<int> x(it1, it2);   // it1 から it2 の範囲で初期化
   set<int> x(y);   // set y で初期化
   set<int> x ({5, 4, 1});   // 初期化子リスト,C++11
   set<int> x {5, 4, 1};   // 初期化子リスト,C++11
   set<int> x = {5, 4, 1};   // 初期化子リスト,C++11		
[メンバー関数等]

[演算子の多重定義]
=  ==  <  <=  !=  >  >=		

[使用例]

  1. set の使用方法です.以下に示すプログラム例において,いくつかのコメント部分は,その上または下に記述された方法とほぼ同等なものであることを示しています(複数行の対応関係である場合もある).
    #include <iostream>
    #include <set>
    
    using namespace std;
    
    void print(string str, set<int> &s) {
    	if (s.empty())
    		cout << "  コンテナ " << str << " は空です\n";
    	else {
    		cout << str << " の要素数: " << s.size() << endl;
    		for (auto x : s)
    			cout << "  " << x;
    //		set<int>::iterator it;
    //		for (it = s.begin(); it != s.end(); it++)
    //			cout << "  " << *it;
    		cout << endl;
    	}
    }
    
    int main()
    {
    					// 初期設定
    	cout << "**初期設定**\n";
    	set<int> s1 = {1, 0, 4, 3, 2};
    	print("s1", s1);
    					// 2 番目の要素の前に要素を追加
    	cout << "**2 番目の要素の前に要素を追加**\n";
    	set<int>::iterator it = s1.begin();
    	it++;
    	s1.insert(it, 5);
    	print("s1", s1);
    					// 3 番目の要素,及び,要素 4 を削除
    	cout << "**3 番目の要素,及び,要素 4 を削除**\n";
    	it = s1.begin();
    	it++;
    	it++;
    	s1.erase(it);
    	s1.erase(4);
    	print("s1", s1);
    					// 要素 3 の位置
    	cout << "**要素 3 の位置**\n";
    	it = s1.find(3);
    	printf("  検索: %d\n", *it);
    					// 交換
    	cout << "**交換**\n";
    	set<int> s2;
    	print("入れ替え前:s1", s1);
    	print("入れ替え前:s2", s2);
    	s1.swap(s2);
    	print("s1", s1);
    	print("s2", s2);
    					// 演算子で比較
    	cout << "**比較**\n";
    	s1.insert(1);
    	s1.insert(0);
    	s1.insert(5);
    	s1.insert(3);
    	print("s1", s1);
    	if (s1 == s2)
    		cout << "  2 つのコンテナ内の要素はすべて等しい\n";
    					// s1 のすべての要素を削除
    	cout << "**s1 のすべての要素を削除**\n";
    	s1.clear();
    	print("s1", s1);
    
    	return 0;
    }
    			
    (出力)
    **初期設定**
    s1 の要素数: 5
      0  1  2  3  4
    **2 番目の要素の前に要素を追加**
    s1 の要素数: 6
      0  1  2  3  4  5
    **3 番目の要素,及び,要素 4 を削除**
    s1 の要素数: 4
      0  1  3  5
    **要素 3 の位置**
      検索: 3
    **交換**
    入れ替え前:s1 の要素数: 4
      0  1  3  5
      コンテナ 入れ替え前:s2 は空です
      コンテナ s1 は空です
    s2 の要素数: 4
      0  1  3  5
    **比較**
    s1 の要素数: 4
      0  1  3  5
      2 つのコンテナ内の要素はすべて等しい
    **s1 のすべての要素を削除**
      コンテナ s1 は空です
    			
  2. set の使用方法です.クラス Test における 2 つの整数値の和が大きい順に並べ替えています.以下に示すプログラム例において,いくつかのコメント部分は,その上または下に記述された方法とほぼ同等なものであることを示しています(複数行の対応関係である場合もある).また,コメントとして記述してあるように,比較演算子のオーバーロード(多重定義)を行えば,二項関数オブジェクトを定義しなくても構いません.
    #include <iostream>
    #include <set>
    #include <string>
    
    using namespace std;
    
    class Test {
    	public:
    		string str;
    		int n1, n2;
    		Test (string str1, int m1, int m2) {
    			str = str1;
    			n1  = m1;
    			n2  = m2;
    		}
    };
    					// 二項関数オブジェクト
    class GT
    {
    	public:
    		bool operator() (Test t1, Test t2) const
    		{
    			if (t1.n1+t1.n2 == t2.n1+t2.n2)
    				return (t1.str > t2.str) ? true : false;
    			else
    				return (t1.n1+t1.n2 > t2.n1+t2.n2) ? true : false;
    		}
    };
    					// < 演算子のオーバーロード
    //bool operator< (Test t1, Test t2)
    //{
    //	if (t1.n1+t1.n2 == t2.n1+t2.n2)
    ///		return (t1.str > t2.str) ? true : false;
    //	else
    //		return (t1.n1+t1.n2 > t2.n1+t2.n2) ? true : false;
    //}
    
    int main()
    {
    	Test t1("abc", 20, 30), t2("xyz", 30, 10), t3("ghq", 40, 50), t4("yyy", 30, 10), t5("xyz", 20, 20);
    					// 二項関数オブジェクトを利用する場合
    	set<Test, GT> s1 = {t1, t2, t3}, s2;
    					// < 演算子のオーバーロードを利用する場合
    //	set<Test> s1 = {t1, t2, t3}, s2;
    					// 初期設定
    	s2.insert(t4);
    //	s2.insert("yyy", 30, 10);   // error
    //	s2.insert({"yyy", 30, 10});   // ok
    	s2.insert(t5);
    //	s2.emplace("xyz", 20, 20);   // ok
    //	s2.emplace({"xyz", 20, 20});   // error
    	cout << "**s1**\n";
    	for (auto x : s1)
    		cout << "  " << x.str << " " << x.n1 << " " << x.n2 << endl;
    	cout << "**s2**\n";
    	for (auto x : s2)
    		cout << "  " << x.str << " " << x.n1 << " " << x.n2 << endl;
    					// merge
    	s1.merge(s2);
    	cout << "**s1 merge後**\n";
    	for (auto x : s1)
    		cout << "  " << x.str << " " << x.n1 << " " << x.n2 << endl;
    	cout << "**s2 merge後**\n";
    	for (auto x : s2)
    		cout << "  " << x.str << " " << x.n1 << " " << x.n2 << endl;
    
    	return 0;
    }
    			
    (出力)
    **s1**
      ghq 40 50
      abc 20 30
      xyz 30 10
    **s2**
      yyy 30 10
      xyz 20 20
    **s1 merge後**
      ghq 40 50
      abc 20 30
      yyy 30 10
      xyz 30 10
    **s2 merge後**
      xyz 20 20
    			
[参照]

vectormapmultimaparrayforward_listlistmultisetpriority_queuequeuestackdequeunordered_mapunordered_multimapunordered_setunordered_multiset

菅沼ホーム 本文目次 演習問題解答例 付録目次 索引