map クラス

[機能]

  連想配列,つまり,添え字として数値以外(キー)を使用してデータを参照できる配列を保持します.set と同様,一般的に二分木として実装され,データは自動的にソートされます.Comp に対しては,比較を行う二項関数オブジェクト名を指定します.指定しないと less (昇順)が選択されます.なお,以下に示す関数において,一般に,insert よりも,emplace を使ったほうが処理効率は良くなります.
template <class Key, class T, class Comp = less<Key>,
class Allocator = allocator<pair<const Key, T>>>
   class map		

[使用方法]
#include <map>
using namespace std;
map <Key, T> 変数名;
   map<int, string> x;   // 空の map,昇順
   map<int, string, greater<int>> x;   // 空の map,降順
   map<int, string> x(it1, it2);   // it1 から it2 の範囲で初期化
   map<int, string> x(y);   // map y で初期化
   map<int, string> x ({{1, "abc"}, {2, "efg"}});   // 初期化子リスト,C++11
   map<int, string> x {{1, "abc"}, {2, "efg"}};   // 初期化子リスト,C++11
   map<int, string> x = {{1, "abc"}, {2, "efg"}};   // 初期化子リスト,C++11		

[メンバー関数等]

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

[使用例]

  1. map の使用方法です.以下に示すプログラム例において,いくつかのコメント部分は,その上または下に記述された方法とほぼ同等なものであることを示しています(複数行の対応関係である場合もある).
    #include <iostream>
    #include <map>
    
    using namespace std;
    
    void print(string str, map<string, int, greater<string>> &m) {
    	if (m.empty())
    		cout << "  コンテナ " << str << " は空です\n";
    	else {
    		cout << str << " の要素数: " << m.size() << endl;
    		for (auto x : m)
    			cout << "  " << x.first << " " << x.second;
    //		map<string, int, greater<string>>::iterator it;
    //		for (it = m.begin(); it != m.end(); it++)
    //			cout << "  " << (*it).first << " " << (*it).second;
    		cout << endl;
    	}
    }
    
    int main()
    {
    					// 要素を追加(サイズは自動的に増加)
    					// キーが string,値が int,大きい順にソート
    	cout << "**初期設定**\n";
    	map<string, int, greater<string>> m1;   // 二項関数オブジェクト greater
    	m1.insert(pair<string, int>("suzuki", 40));
    	m1.insert(pair<string, int>("sato", 60));
    	m1.insert(pair<string, int>("yamada", 70));
    	m1.insert(pair<string, int>("tanaka", 50));
    	m1.insert(pair<string, int>("kato", 90));
    	print("m1", m1);
    					// 2 番目の要素の前に要素を追加
    	cout << "**2 番目の要素の前に要素を追加**\n";
    	map<string, int, greater<string>>::iterator it = m1.begin();
    	it++;
    	m1.insert(it, pair<string, int>("naito", 20));
    	print("m1", m1);
    					// 2 番目の要素,及び,要素 sato を削除
    	cout << "**2 番目の要素,及び,要素 sato を削除**\n";
    	it = m1.begin();
    	it++;
    	m1.erase(it);
    	m1.erase("sato");
    	print("m1", m1);
    					// キー suzuki の値
    	cout << "**キー suzuki の値**\n";
    	it = m1.find("suzuki");
    	cout << "  値: " << it->second << endl;
    	cout << "  値: " << m1.at("suzuki") << endl;
    	cout << "  値: " << m1["suzuki"] << endl;
    					// 演算子で比較
    	cout << "**比較**\n";
    	map<string, int, greater<string>> m2 = {{"naito", 20}, {"suzuki", 40},
    	                                        {"yamada", 70}, {"kato", 90}};
    	print("m2", m2);
    	if (m1 == m2)
    		cout << "  2 つのコンテナ内の要素はすべて等しい\n";
    					// ヒントと insert_or_assign,try_emplace
    	cout << "ヒントと insert_or_assign\n";
    	m1.emplace_hint(m1.begin(), "wada", 10);   // 先頭近傍に挿入されることが既知
    	print("m1", m1);
    	pair<map<string, int, greater<string>>::iterator, bool> p;
    	p = m1.insert_or_assign("wada", 20);
    	cout << "存在した場合(insert_or_assign) " << (*p.first).second << " " << p.second << " ";
    	print("m1", m1);
    	p = m1.try_emplace("wada", 100);
    	cout << "存在した場合(try_emplace) " << (*p.first).second << " " << p.second << " ";
    	print("m1", m1);
    	p = m1.insert_or_assign("aoki", 50);
    	cout << "存在しなかったた場合(insert_or_assign) " << (*p.first).second << " " << p.second << " ";
    	print("m1", m1);
    					// [] 演算子( ["tanaka"] )
    	cout << "**[] 演算子( [\"tanaka\"] )**\n";
    	cout << m1["tanaka"] << endl;   // 参照した時点で追加される
    //	cout << m1.at("tanaka") << endl;   // キーが存在しないときは out_of_range 例外	print("m1", m1);
    	m1["tanaka"] = 100;
    	print("m1", m1);
    					// 交換
    	cout << "**交換**\n";
    	print("入れ替え前:m1", m1);
    	print("入れ替え前:m2", m2);
    	m1.swap(m2);
    	print("m1", m1);
    	print("m2", m2);
    					// m1 のすべての要素を削除
    	cout << "**m1 のすべての要素を削除**\n";
    	m1.clear();
    	print("m1", m1);
    
    	return 0;
    }
    			
    (出力)
    **初期設定**
    m1 の要素数: 5
      yamada 70  tanaka 50  suzuki 40  sato 60  kato 90
    **2 番目の要素の前に要素を追加**
    m1 の要素数: 6
      yamada 70  tanaka 50  suzuki 40  sato 60  naito 20  kato 90
    **2 番目の要素,及び,要素 sato を削除**
    m1 の要素数: 4
      yamada 70  suzuki 40  naito 20  kato 90
    **キー suzuki の値**
      値: 40
      値: 40
      値: 40
    **比較**
    m2 の要素数: 4
      yamada 70  suzuki 40  naito 20  kato 90
      2 つのコンテナ内の要素はすべて等しい
    ヒントと insert_or_assign
    m1 の要素数: 5
      yamada 70  wada 10  suzuki 40  naito 20  kato 90
    存在した場合(insert_or_assign) 20 0 m1 の要素数: 5
      yamada 70  wada 20  suzuki 40  naito 20  kato 90
    存在した場合(try_emplace) 20 0 m1 の要素数: 5
      yamada 70  wada 20  suzuki 40  naito 20  kato 90
    存在しなかったた場合(insert_or_assign) 50 1 m1 の要素数: 6
      yamada 70  wada 20  suzuki 40  naito 20  kato 90  aoki 50
    **[] 演算子( ["tanaka"] )**
    0
    m1 の要素数: 7
      yamada 70  wada 20  tanaka 100  suzuki 40  naito 20  kato 90  aoki 50
    **交換**
    入れ替え前:m1 の要素数: 7
      yamada 70  wada 20  tanaka 100  suzuki 40  naito 20  kato 90  aoki 50
    入れ替え前:m2 の要素数: 4
      yamada 70  suzuki 40  naito 20  kato 90
    m1 の要素数: 4
      yamada 70  suzuki 40  naito 20  kato 90
    m2 の要素数: 7
      yamada 70  wada 20  tanaka 100  suzuki 40  naito 20  kato 90  aoki 50
    **m1 のすべての要素を削除**
      コンテナ m1 は空です
    			
  2. map の使用方法です.クラス Test における整数値の和が大きい順にソートしています.コメントとして記述してあるように,比較演算子のオーバーロード(多重定義)を行えば,二項関数オブジェクトを定義しなくても構いません.
    #include <iostream>
    #include <map>
    #include <string>
    
    using namespace std;
    
    class Test {
    	public:
    		int n1, n2;
    		Test (const int& m1, const int& m2) {
    			n1 = m1;
    			n2 = m2;
    		}
    };
    			// 二項関数オブジェクト
    			// const は,関数内でメンバ変数の変更ができないことを意味する
    class GT
    {
    	public:
    		bool operator() (Test t1, Test t2) const
    		{
    			return (t1.n1+t1.n2 > t2.n1+t2.n2) ? true : false;
    		}
    };
    			// < 演算子のオーバーロード
    //bool operator< (Test t1, Test t2)
    //{
    //	return (t1.n1+t1.n2 > t2.n1+t2.n2) ? true : false;
    //}
    
    int main()
    {
    	Test t1(20, 30), t2(30, 10), t3(40, 50), t4(10, 10), t5(30, 30), t6(20, 30);
    	map<Test, string, GT> s1;   // 二項関数オブジェクト
    //	map<Test, string> s1;   // < 演算子のオーバーロード(多重定義)
    			// 初期状態 s1
    	s1.insert(pair<Test, string>(t1, "abc"));
    	s1.insert(pair<Test, string>(t2, "kkk"));
    	s1.insert(pair<Test, string>(t2, "kkk"));
    	s1.insert(pair<Test, string>(t3, "xyz"));
    	cout << "初期状態 s1\n";
    	for (auto x : s1)
    		cout << " (" << (x.first).n1 << ", " << (x.first).n2 << ") " << x.second << endl;
    			// 初期状態 s2
    	map<Test, string, GT> s2 = {{t4, "aaa"}, {t5, "bbb"}, {t6, "ccc"}};   // 二項関数オブジェクト
    //	map<Test, string> s2 = {{t4, "aaa"}, {t5, "bbb"}, {t6, "ccc"}};   // < 演算子のオーバーロード
    	cout << "初期状態 s2\n";
    	for (auto x : s2)
    		cout << " (" << (x.first).n1 << ", " << (x.first).n2 << ") " << x.second << endl;
    			// merge
    	s1.merge(s2);
    	cout << "merge 後 s1\n";
    	for (auto x : s1)
    		cout << " (" << (x.first).n1 << ", " << (x.first).n2 << ") " << x.second << endl;
    	cout << "merge 後 s2\n";
    	for (auto x : s2)
    		cout << " (" << (x.first).n1 << ", " << (x.first).n2 << ") " << x.second << endl;
    
    	return 0;
    }
    			
    (出力)
    初期状態 s1
     (40, 50) xyz
     (20, 30) abc
     (30, 10) kkk
    初期状態 s2
     (30, 30) bbb
     (20, 30) ccc
     (10, 10) aaa
    merge 後 s1
     (40, 50) xyz
     (30, 30) bbb
     (20, 30) abc
     (30, 10) kkk
     (10, 10) aaa
    merge 後 s2
     (20, 30) ccc
    			
[参照]

vectorsetmultimaparrayforward_listlistmultisetpriority_queuequeuestackdequeunordered_mapunordered_multimapunordered_setunordered_multiset

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