マップとセットの具体的な使用法 [C++]

連想コンテナ

連想コンテナには、<key, value> 構造のキーと値のペアが格納され、データの取得においては順次コンテナよりも効率的です。例: set、map、unowned_set、unowned_map など。

: C++STL の stack、queue、priority_queue はコンテナ アダプタに属し、デフォルトで使用される基本コンテナはそれぞれ deque、deque、vector です。

キーと値のペア

キーと値のペアは、1 対 1対応の構造を表すために使用されます。この構造には通常、キーと値の 2 つのメンバー変数のみが含まれます。キーはキーの値を表し、値はキーに対応する情報を表します。

たとえば、英語と中国語の辞書を作成する場合、辞書内の英語の単語とそれに対応する中国語の意味の間には 1 対 1 の対応関係があり、単語を通じて対応する中国語の意味を見つけることができます。

SGI-STL におけるキーと値のペアの定義は次のとおりです。

template <class T1, class T2>
struct pair
{
    
    
	typedef T1 first_type;
	typedef T2 second_type;
	T1 first;
	T2 second;
	pair() 
	: first(T1())
	, second(T2())
	{
    
    
	}
	pair(const T1& a, const T2& b) 
	: first(a)
	, second(b)
	{
    
    
	}
};

セット

1. セットは要素を特定の順序で格納するコンテナであり、セットのイテレータを使用してセット内の要素を走査すると、順序付けられたシーケンスを取得できます。

2. セットに保存されている要素の値は一意であり、繰り返すことができないため、セットを使用して重複を削除できます。

3. map/multimap とは異なり、map/multimap は実際のキーと値のペア <key, value> を格納します。set には value のみが配置されますが、実際には <value, value> で構成されるキーと値のペアが最下位に格納されます。 、要素を set コンテナーに挿入するときは、値を挿入するだけで済み、キーと値のペアを構築する必要はありません。

4. セット内の要素は変更できません。セットは下部の二分探索ツリーを使用して実装されます。二分探索ツリー内のノードの値が変更されると、ツリーは二分探索ツリーではなくなります。検索ツリー

5. 内部的には、セット内の要素は、内部比較オブジェクトによって示される特定の厳密で弱い並べ替え基準に従って常に並べ替えられます。内部比較オブジェクトが渡されない場合、セット内の要素はデフォルトで以下のものとして比較されます。

6. set コンテナの key を介した単一要素へのアクセスは、通常、unowned_set コンテナよりも遅くなりますが、set コンテナでは順序に従って要素を直接反復できます。

7. セットは、最下位レベルでバランスの取れた検索ツリー (赤黒ツリー) を使用して実装されるため、セット内の要素を見つける時間計算量はlogNです。

セットの定義方法

//构造int类型的空容器
set<int> s1; 

//拷贝构造int类型s1
set<int> s2(s1); 
string str("abcdef");

//拷贝string
set<char> s3(str.begin(), str.end()); 

//构造int类型的空容器,比较方式指定为大于
set < int, greater<int>> s4; 

セットの使用

void Testset()
{
    
    
	 //去重
	set<int> s;
	s.insert(1);
	s.insert(4);
	s.insert(3);
	s.insert(3);
	s.insert(2);
	s.insert(2);
	s.insert(3);
	//遍历方式一

	for (auto e : s)
	{
    
    
		cout << e << " ";
	}
	cout << endl;
	//删除方式一
	s.erase(3);
	//遍历方式二

	set<int>::iterator it = s.begin();
	while (it != s.end())
	{
    
    
		cout << *it << " ";
		it++;
	}
	cout << endl;
	//删除方式二, 正向迭代器遍历 
	set<int>::iterator pos = s.find(1);
	if (pos!=s.end())
	{
    
    
		s.erase(pos);
	}
	//遍历方式三
	set<int>::reverse_iterator rit = s.rbegin();
	while (rit != s.rend())
	{
    
    
		cout << *rit << " ";
		rit++;
	}
	cout << endl;
	//容器中值为2的个数 
	cout<<s.count(2);
	cout << s.size();
	s.clear();
	cout << s.empty();

}

void TestmultiSet()
{
    
    
	//可以重复 
	multiset<int> m;
	m.insert(3);
	m.insert(5);
	m.insert(8);
	m.insert(7);
	m.insert(7);
	m.insert(9);
	m.insert(7);
	for (auto e : m)
	{
    
    
		cout << e << "";
	}
	//find 
	//set<int> s;
	//s.insert(1);
	//s.insert(4);
	//s.insert(3);
	//s.insert(3);
	//s.insert(2);
	//s.insert(2);
	//s.insert(3);
	//if (s.find(3) != s.end())
	//{
    
    
	//	cout << "找到了" << " ";
	//}
	//else
	//{
    
    
	//	cout << "找不到" << " ";
	//}
	auto pos = m.find(7);//返回中序中第一个7
	while (pos != m.end())
	{
    
    
		cout << *pos << " ";
		pos++;
	}
	cout << endl;
	cout << m.count(7) << endl;
	auto ret = m.equal_range(17);
	auto itlow = ret.first;
	auto itup = ret.second;
	//[itlow , itup) 左闭右开 左边界是第一个7,右边界是比7大的,才能完全删除所有的7
	cout << *itlow<<endl;
	cout << *itup<<endl;
	m.erase(itlow, itup);//?
	for (auto e : m)
	{
    
    
		cout << e << " ";
	}
	cout << endl;
	
}
void Testset2()
{
    
    
	set<int> s;
	s.insert(1);
	s.insert(4);
	s.insert(3);
	s.insert(3);
	s.insert(2);
	s.insert(2);
	s.insert(3);
	//交换两个容器的数据 
	set<int> tmp{
    
     11,22,33,44 };
	s.swap(tmp);
	for (auto e : s)
	{
    
    
		cout << e << " ";
	}
	cout << endl;
}

int main()
{
    
    
Testset();
TestmultiSet();
Testset2();
return 0 ;
}

マルチセット

マルチセット コンテナとセット コンテナの基礎となる実装は同じであり、どちらもバランス検索ツリー (赤黒ツリー) です。第二に、マルチセット コンテナとセット コンテナによって提供されるメンバ関数のインターフェイスは基本的に同じです。マルチセット コンテナとセット コンテナの唯一の違いは、マルチセットではキー値の冗長性が許可されることです。つまり、マルチセット コンテナに格納されている要素を繰り返すことができます。

#include <iostream>
#include <set>
using namespace std;

int main()
{
    
    
	multiset<int> ms;
	//插入元素(允许重复)
	ms.insert(1);
	ms.insert(4);
	ms.insert(3);
	ms.insert(3);
	ms.insert(2);
	ms.insert(2);
	ms.insert(3);
	for (auto e : ms)
	{
    
    
		cout << e << " ";
	}
	cout << endl; //1 2 2 3 3 3 4
	return 0;
}

ここに画像の説明を挿入します

地図

1. Map は連想コンテナです。キーと値で構成される要素を特定の順序 (キーで比較) で格納します。map のイテレータを使用してマップ内の要素を走査すると、順序付けされたシーケンスを取得できます。

2. マップでは、通常、キー値キーは要素を並べ替えて一意に識別するために使用され、値値はこのキー値キーに関連付けられたコンテンツを格納します。キーと値の型は異なる場合があり、マップ内では、キーと値はメンバー型 value_type を通じてバインドされ、ペアとしてエイリアス化されます。

3. マップ コンテナ内の要素のキー値は変更できませんが、マップの基礎となる二分探索ツリーが値ではなく各要素のキー値に基づいて構築されるため、要素の値は変更できます。

4. 内部的には、マップ内の要素が常に比較され、キー値に従って並べ替えられます。内部比較オブジェクトが渡されない場合、デフォルトでは、マップ内の要素のキー値が小さいかどうかで比較されます。

5. マップ コンテナは一般に、キー値を介して単一の要素にアクセスする際に unowned_map コンテナよりも遅くなりますが、マップ コンテナでは順序に従って要素を直接反復できます。

6. マップ コンテナは添字アクセス演算子をサポートしています。つまり、[] にキーを入れると、キーに対応する値を見つけることができます。

7. マップは最下位レベルでバランスのとれた検索ツリー (赤黒ツリー) を使用して実装されるため、マップ内の要素を見つける時間計算量は logN です。

マップの定義方法

map<int, double> m1; //构造一个key为int类型,value为double类型的空容器

map<int, double> m2(m1); //拷贝构造key为int类型,value为double类型的m1容器的复制品

map<int, double> m3(m2.begin(), m2.end()); //使用迭代器拷贝构造m2容器某段区间的复制品

map<int, double, greater<int>> m4; //构造一个key为int类型,value为double类型的空容器,key比较方式指定为大于

入れる

ここに画像の説明を挿入します

pair<iterator,bool> insert (const value_type& val);

Value_type タイプ、実際には value_type はペア タイプのエイリアスです。

typedef pair<const Key, T> value_type;

要素を挿入するときは、キーと値を使用してペア オブジェクトを構築し、そのペア オブジェクトをパラメータとして挿入関数に渡す必要があります。

方法 1:匿名オブジェクト

#include <iostream>
#include <string>
#include <map>
using namespace std;

int main()
{
    
    
	map<int, string> m;
	//方式一:调用pair的构造函数,构造一个匿名对象插入
	m.insert(pair<int, string>(2, "two"));
	m.insert(pair<int, string>(1, "one"));
	m.insert(pair<int, string>(3, "three"));
	for (auto e : m)
	{
    
    
		cout << "<" << e.first << "," << e.second << ">" << " ";
	}
	cout << endl; //<1,one> <2,two> <3,three>
	return 0;
}

方法 2: make_pair 関数の呼び出しテンプレート挿入 (一般的に使用されます)

ライブラリは、次の make_pair 関数テンプレートを提供します。

template <class T1, class T2>
pair<T1, T2> make_pair(T1 x, T2 y)
{
    
    
	return (pair<T1, T2>(x, y));
}

make_pair 関数にキーと値を渡すと、関数テンプレートは渡されたパラメーターの型を自動的かつ暗黙的に推定し、最終的に対応するペア オブジェクトを構築して返します。

#include <iostream>
#include <string>
#include <map>
using namespace std;

int main()
{
    
    
	map<int, string> m;
	//方式二:调用函数模板make_pair,构造对象插入
	m.insert(make_pair(2, "two"));
	m.insert(make_pair(1, "one"));
	m.insert(make_pair(3, "three"));
	for (auto e : m)
	{
    
    
		cout << "<" << e.first << "," << e.second << ">" << " ";
	}
	cout << endl; //<1,one> <2,two> <3,three>
	return 0;
}

挿入関数の戻り値は
ここに画像の説明を挿入します
ドキュメントの内容を要約します:
挿入関数の戻り値もペア オブジェクトです。ペア オブジェクトの最初のメンバーの型はマップのイテレータ型で、2 番目のメンバーの型はマップのイテレータ型です。 member は bool 型であり、具体的な意味は次のとおりです。

1. 挿入する要素のキー値がマップに存在しない場合、挿入関数は正常に挿入され、挿入された要素のイテレータと true を返します。
2. 挿入する要素のキー値がマップ内にすでに存在する場合、挿入関数は挿入に失敗し、マップ内のキー値が key である要素のイテレータと false を返します。

探す

ここに画像の説明を挿入します

iterator find (const key_type& k);

指定されたキー値に従ってマップを検索します。見つかった場合は、対応する要素のイテレータが返されます。見つからなかった場合は、コンテナ内の最後の要素の次の位置の前方イテレータが返されます。

#include <iostream>
#include <string>
#include <map>
using namespace std;

int main()
{
    
    
	map<int, string> m;
	m.insert(make_pair(2, "two"));
	m.insert(make_pair(1, "one"));
	m.insert(make_pair(3, "three"));
	//获取key值为2的元素的迭代器
	map<int, string>::iterator pos = m.find(2);
	if (pos != m.end())
	{
    
    
		cout << pos->second << endl; //two
	}
	return 0;
}

消す

ここに画像の説明を挿入します
キー値に基づいて指定された要素を削除するか、イテレータに基づいて指定された要素を削除します。キー値に基づいて要素を削除した場合は、実際に削除された要素の数が返されます。

#include <iostream>
#include <string>
#include <map>
using namespace std;

int main()
{
    
    
	map<int, string> m;
	m.insert(make_pair(2, "two"));
	m.insert(make_pair(1, "one"));
	m.insert(make_pair(3, "three"));
	for (auto kv : m)
	{
    
    
		cout << kv.first<<" " << kv.second;
	}
	cout << endl;
	//根据key值进行删除
	m.erase(3);
	for ( auto kv : m)
	{
    
    
		cout << kv.first << " " << kv.second;
	}
	//根据迭代器删除 
	map<int, string>::iterator pos = m.find(2);
	while (pos != m.end())
	{
    
    
		m.erase(pos);
	}
	for (auto kv : m)
	{
    
    
		cout << kv.first << " " << kv.second;
	}
	return 0;
}

[] 演算子のオーバーロード

ここに画像の説明を挿入します
ここに画像の説明を挿入します
[ ] 演算子オーバーロード関数のパラメータはキー値であり、この関数の戻り値は次のとおりです。

(* (  (this->insert(  make_pair(k, mapped_type() ) ) ).first)   ).second

上記のコードによれば、演算子のオーバーロード実装のロジック [ ] は次のように推測できます。

mapped_type& operator[] (const key_type& k)
{
    
    
	//1、调用insert函数插入键值对
	pair<iterator, bool> ret = insert( make_pair(k, mapped_type() ) );
	//2、拿出从insert函数获取到的迭代器
	iterator it = ret.first;
	//3、返回该迭代器位置元素的值value
	return it->second;
}

[] 演算子の使用

int main()
{
    
    
		 map<string, string> dict;
		 dict.insert(make_pair("string", "字符串"));
		 dict.insert(make_pair("sort", "排序"));
		 dict.insert(make_pair("insert", "插入"));
	
		 cout << dict["sort"] << endl;//查找和读
		 dict["map"];//插入
		 dict["map"] = "映射,地图";//修改
		 dict["insert"] = "xxx";//修改
		 dict["set"] = "集合";//插入+修改
}

要約すると:
1. k がマップにない場合は、最初にキーと値のペア <k, V()> を挿入し、次にキーと値のペア内の V オブジェクトへの参照を返します。
2. k がすでにマップ内にある場合は、キー値 k を持つ要素に対応する V オブジェクトの参照を返します。

マップ反復子のトラバーサル

int main()
{
    
    
	map<int, string>  m;
	m.insert(make_pair(2, "two"));
	m.insert(make_pair(1, "one"));
	m.insert(make_pair(3, "three"));

	//正向迭代器 
	map<int, string>::iterator   it = m.begin();
	while (it != m.end())
	{
    
    
		//cout << (*it).first << ":"<<(*it).second<<endl;//迭代器重载operator*
		cout << it->first << ":" << it->second << endl;//迭代器重载operator->
		it++;	
	}
	cout << endl;
	//反向迭代器 
	map<int, string>::reverse_iterator rit = m.rbegin();
	while (rit != m.rend())
	{
    
    
		cout << " " << rit->first << " " << rit->second;
		rit++;
	}
	cout << endl;
	//范围for ,kv就是*it
	for (auto kv : m)
	{
    
    
		cout << kv.first <<" " << kv.second;
	}
	return 0;
}

マルチマップ

マルチマップ コンテナの基礎となる実装は、マップ コンテナの実装と同じです。これらはバランス検索ツリー (赤黒ツリー) でもあります。マルチマップ コンテナとマップ コンテナの違いは、マルチセット コンテナとセット コンテナの違いと同じです。キー値の冗長性が可能になります。つまり、マルチマップ コンテナー内で、格納された要素を繰り返すことができます。

#include <iostream>
#include <string>
#include <map>
using namespace std;

int main()
{
    
    
	multimap<int, string> mm;
	//插入元素(允许重复)
	mm.insert(make_pair(2, "two"));
	mm.insert(make_pair(2, "double"));
	mm.insert(make_pair(1, "one"));
	mm.insert(make_pair(3, "three"));
	for (auto e : mm)
	{
    
    
		cout << "<" << e.first << "," << e.second << ">" << " ";
	}
	cout << endl; //<1,one> <2,two> <2,double> <3,three>
	return 0;
}

ここに画像の説明を挿入します
この記事が少しでも役に立ったと思っていただけましたら、いいね、集めてリポストしてHudに注目していただけると励みになります

おすすめ

転載: blog.csdn.net/qq_73478334/article/details/133214906