-
map是C++中的一种键值对容器,要点就是数据在map中是成对出现的,能够通过键也就是key来快速找到对应的值。要想使用标准C++中map类,必须要包含头文件:#include < map >
-
map是一类关联式容器。它的特点是增加和删除节点对迭代器的影响很小,除了那个操作节点,对其他的节点都没有什么影响。
-
对于迭代器来说,可以修改实值,而不能修改key。
1、构造函数
map < string , int > mapstring;
map < int , string > mapint;
map < sring , char > mapstring;
map < char , string > mapchar;
map < char , int > mapchar;
map < int , char > mapint;
map构造函数内部升序和降序的设置:
// ----------------------- 默认升序
map<int, double, less<int> > m0 = { { 9,1.1 },{ 2,2.2 },{ 0,3.6 },{ 3,4.5 } };
for (auto it = m0.begin(); it != m0.end(); ++it) {
cout << it->first << ":" << it->second << " "; // 0:3.6 2:2.2 3:4.5 9:1.1
}
// ----------------------- 仿函数greater<T>()降序
map<int, double, greater<int> > m = { {9,1.1},{2,2.2},{0,3.6},{3,4.5} };
for (auto it = m.begin(); it != m.end(); ++it) {
cout << it->first <<":"<< it->second<<" "; // 9:1.1 3:4.5 2:2.2 0:3.6
}
cout << endl;
// -----------------------仿函数less<T>()降序
map<int, double, less<int> > m1 = { { 9,1.1 },{ 2,2.2 },{ 0,3.6 },{ 3,4.5 } };
for (auto it = m1.begin(); it != m1.end(); ++it) {
cout << it->first << ":" << it->second << " "; // 0:3.6 2:2.2 3:4.5 9:1.1
}
map<key, value> maps;
map<T, T> maps;
// key 和 value可以是任意你需要的类型
//声明一个map; map的键值对类型可以是基础数据类型,也可以是结构体或类。
我们通常用如下方法构造一个map:
map<string, value> maps;
map<int, value> maps;
int main() {
//----------------------1、map 构造/初始化;
map<string, int> m1; // 创建一个空map容器
map<string, int> m2 = { {"bbb",1},{"aaa",2},{"ccc",3} };
map<string, int> m3 = {pair<string,int>("bbb",1),pair<string,int> ("aaa",2),pair<string,int> ("ccc",3)};
map<string, int> m4 = { make_pair<string,int>("bbb",1),make_pair<string,int>("aaa",2),make_pair<string,int>("ccc",3) };
//-------------------- 2、map 拷贝构造函数
map<string, int> m5 = m2;
map<string, int> m6(m3);
cout << m1.size() << endl; // 0
cout << m2.size() << endl; // 3
cout << m3.size() << endl; // 3
cout << m4.size() << endl; // 3
cout << m5.size() << endl; // 3
cout << m6.size() << endl; // 3
for (auto it = m1.begin(); it != m1.end(); ++it) {
cout << it->first << ":" << it->second << " "; // (null)
}
cout << endl;
for (auto it = m2.begin(); it != m2.end(); ++it) {
cout << it->first << ":" << it->second << " "; // aaa:2 bbb:1 ccc:3
}
cout << endl;
for (auto it = m3.begin(); it != m3.end(); ++it) {
cout << it->first << ":" << it->second << " ";// aaa:2 bbb:1 ccc:3
}
cout << endl;
for (auto it = m4.begin(); it != m4.end(); ++it) {
cout << it->first << ":" << it->second << " ";// aaa:2 bbb:1 ccc:3
}
cout << endl;
for (auto it = m5.begin(); it != m5.end(); ++it) {
cout << it->first << ":" << it->second << " ";// aaa:2 bbb:1 ccc:3
}
cout << endl;
for (auto it = m6.begin(); it != m6.end(); ++it) {
cout << it->first << ":" << it->second << " ";// aaa:2 bbb:1 ccc:3
}
cout << endl;
return 0;
}
2、map迭代器
和vector一样,map也存在迭代器,方便对map进行遍历操作,map中也存在begin,end,rbegin,rend,前两者为顺序的头尾迭代器,后两者为逆序的头尾迭代器。
map<int, string>::iterator iter = my_map.begin();
3、增
map内部是自动排序号的(以key排序),单词则按字母序排序。
3.1 下标[ ]插入
map<int, string> m1;
m1[9] = "张三";
m1[10] = "李四";
3.2 insert()函数
【注意】
map<string, int> m3;
m3.insert(“aaaa”,2); // 报错 ❌
m3.insert({“aaaa”,2}); // ✔
m.insert(pair<string,int>(“c”,3));
m.insert(make_pair<string,int>(“d”,4));
m.insert(make_pair(“d”, 4));
m.insert(map<string,int>(“d”,4)); ❌
m.insert(map<string, int>::value_type(“hi”,123)); ✔
int main()
{
// ----------------------- 仿函数greater<T>()降序
map<string, int,greater<string>> m ;
m.insert(make_pair("d", 4));
m.insert(pair<string, int>("c", 3));
m.insert(make_pair<string, int>("f", 4));
for (auto it = m.begin(); it != m.end(); ++it) {
cout << it->first <<":"<< it->second<<" "; // f:4 d:4 c:3
}
return 0;
}
3.3 emplace()——用法同insert()
-
原型:pair<iterator,bool> emplace (Args&&… args);
m.emplace(pair<string,int>(“c”,3));
m.emplace(make_pair<string,int>(“d”,4));
m.emplace(make_pair(“d”, 4));
m.emplace(map<string,int>(“d”,4)); ❌
m.emplace(map<string, int>::value_type(“hi”,123)); ✔ -
emplace(pair<key,value>(a,b)比insert()效率高
-
返回值
注意的是,emplace()方法的返回值为 pair 类型值,其包含
一个迭代器
和一个 bool 类型值
:- 当 emplace() 成功添加新键值对时,返回的迭代器指向新添加的键值对,bool 值为 True;
- 当 emplace() 添加新键值对失败时,说明容器中本就包含一个键相等的键值对,此时返回的迭代器指向的就是容器中键相同的这个键值对,bool 值为 False。
int main()
{
// ----------------------- 仿函数greater<T>()降序
map<string, int,greater<string>> m ;
m.emplace(make_pair("d", 4));
m.emplace(pair<string, int>("c", 3));
m.emplace(make_pair<string, int>("f", 4));
m.emplace(map<string, int>::value_type("hi", 123));
for (auto it = m.begin(); it != m.end(); ++it) {
cout << it->first <<":"<< it->second<<" "; // hi:123 f:4 d:4 c:3
}
cout << endl;
return 0;
}
3.4 emplace_hint()
原型:iterator emplace_hint ( iterator, T);
和 emplace() 方法相同,emplace_hint() 方法内部会自行构造新键值对,因此我们只需向其传递构建该键值对所需的 2 个元素(第一个作为键,另一个作为值)即可。不同之处在于:
- emplace_hint() 方法的返回值仅是一个迭代器,而不再是 pair 类型变量。当该方法将新键值对成功添加到容器中时,返回的迭代器指向新添加的键值对;反之,如果添加失败,该迭代器指向的是容器中和要添加键值对键相同的那个键值对。
- emplace_hint() 方法还需要传递一个迭代器作为第一个参数,该
迭代器表明将新键值对添加到容器中的位置
。需要注意的是,新键值对添加到容器中的位置,并不是此迭代器说了算,最终仍取决于该键值对的键的值。map<string, int, greater> m;
auto it = m.emplace(make_pair(“你好”, 333)); // 返回新插入元素的
m.emplace_hint(it.first
,make_pair(“d”, 4));
int main()
{
// ----------------------- 仿函数greater<T>()降序
/*
* emplace_hint() 方法还需要传递一个迭代器作为第一个参数,
* 该迭代器表明将新键值对添加到容器中的位置。
* 需要注意的是,新键值对添加到容器中的位置,
* 并不是此迭代器说了算,最终仍取决于该键值对的键的值。
*/
// ----------------------- 仿函数greater<T>()降序
/*
* emplace_hint() 方法还需要传递一个迭代器作为第一个参数,
* 该迭代器表明将新键值对添加到容器中的位置。
* 需要注意的是,新键值对添加到容器中的位置,
* 并不是此迭代器说了算,最终仍取决于该键值对的键的值。
*/
map<string, int, greater<string>> m;
auto it = m.emplace(make_pair("你好", 333));
m.emplace_hint(m.begin(), make_pair("d", 4));
m.emplace_hint(it.first, pair<string, int>("c", 3));
/* m.emplace_hint(it.first,map<string, int>("x", 4)); */
m.emplace_hint(it.first, make_pair<string, int>("f", 4));
m.emplace_hint(it.first, map<string, int>::value_type("hi", 123));
for (auto it = m.begin(); it != m.end(); ++it) {
cout << it->first << ":" << it->second << " "; // 你好:333 hi:123 f:4 d:4 c:3
}
cout << endl;
return 0;
}
int main()
{
// ----------------------- 仿函数greater<T>()降序
/*
* emplace_hint() 方法还需要传递一个迭代器作为第一个参数,
* 该迭代器表明将新键值对添加到容器中的位置。
* 需要注意的是,新键值对添加到容器中的位置,
* 并不是此迭代器说了算,最终仍取决于该键值对的键的值。
*/
map<string, string>mymap;
//指定在 map 容器插入键值对
auto iter = mymap.emplace_hint(mymap.begin(), "张三", "甲");
cout << iter->first << " " << iter->second << endl; // 张三 甲
iter = mymap.emplace_hint(mymap.begin(), "李四", "乙");
cout << iter->first << " " << iter->second << endl; // 李四 乙
for (auto it = mymap.begin(); it != mymap.end(); ++it) {
cout << it->first << ":" << it->second << " "; // 李四:乙 张三:甲
}
cout << endl;
return 0;
}
[ ] 和 insert() 区别
1. 这里要注意比较关键的一点是上述两种方式插入的结果可能是不同的。
当key在map中已经存在时:通过下标插入会直接覆盖之前的值,而insert则不会插入。
2. 还有一点特别要注意的是不要用下标来查找map中是否存在某键值对,这会导致map中插入新的值或者之前的值被覆盖。
3.4 代码演示
int main() {
//-------------------------------------------------1、 数组法插入
//++++++++++++++++++++++++++++ 1.map<int, string> m1;
map<int, string> m1;
m1[9] = "张三";
m1[10] = "李四";
//********* 数组法遍历
for (size_t i = 0; i < m1.size(); ++i) {
cout << m1[i] << " "; //( 空 )张三 李四
}
cout << endl;
//*********迭代器遍历
for (auto it = m1.begin(); it != m1.end(); ++it) {
cout << it->first << ":" << it->second << " "; // 0: 1: 2: 3: 4: 5: 6: 7: 8: 9:张三 10:李四
}
//++++++++++++++++++++++++++++ 2. map<char, string> m2;
map<char, string> m2;
m2['s'] = "张三";
m2['f'] = "李四";
//********* 数组法遍历
for (size_t i = 0; i < m2.size(); ++i) {
cout << m2[i] << " "; // 李四 张三
}
//*********迭代器遍历
cout << " ---------------------------"<<endl;
for (auto it = m2.begin(); it != m2.end(); ++it) {
cout << it->first << ":" << it->second << " ";
// 输出:
// : : : : : : : : : :
// : : : : : : : : : : : : : : : : : : : : !: ": #: $: %: &: ': (: ): *: +: ,: -: .: /: 0: 1: 2: 3: 4: 5: 6: 7: 8: 9: :: ;: <: =: >: ?: @: A: B: C: D: E: F: G: H: I: J: K: L: M: N: O: P: Q: R: S: T: U: V: W: X: Y: Z: [: \: ]: ^: _: `: a: b: c: d: e: f:李四 g: h: i: j: k: l: m: n: o: p: q: r: s:张三
}
//----------------------1、 insert()插入
map<string, int> m3;
m3.insert(pair<string, int>("bb", 2));
m3.insert(pair<string, int>("aa", 8));
m3.insert(pair<string, int>("ff", 0));
m3.insert(pair<string, int>("ee", -4));
cout << endl<< "_________________________" << endl;
for (auto it = m3.begin(); it != m3.end(); ++it) {
cout <<it->first << ":" << it->second << " "; // aa 8 bb 2 ee -4 ff 0
}
map<string, string> m4;
m4.insert(pair<string, string>("bb", "张三"));
m4.insert(pair<string, string>("aa", "李四"));
m4.insert(pair<string, string>("ff", "王五"));
m4.insert(pair<string, string>("ee", "LIBSD"));
cout << endl << "_________________________" << endl;
for (auto it = m4.begin(); it != m4.end(); ++it) {
cout << it->first << ":" << it->second << " "; //aa:李四 bb:张三 ee:LIBSD ff:王五
}
return 0;
}
4、删
4.1 erase()
4.1.1 map中删除数据主要有三种方式:
- 通过迭代器删除某个键值对;
- 通过迭代器删除某些键值对;
- 旧方法:m2.erase(it++); // 防止迭代器失效
- 通过key删除键值对。
iterator erase(iterator it);//通过一个条目对象删除
iterator erase(iterator first,iterator last);//删除一个范围
size_type erase(key);//通过关键字删除
4.1.2 返回值
- my_map.erase(iter); // 返回iter 的下一个元素的迭代器
- my_map.erase(begin_iter, end_iter); // 返回end_iter 的下一个元素的迭代器
- m2.erase(it++); // 防止迭代器失效,it自动+1(指向下一个元素)
- my_map.erase(key); // 返回值:如果在映射中找到关键元素,则函数返回1,否则返回0。即:删除成功返回1,失败返回0;
【注意】
4.2 clear()
my_map.clear(); //清除map中所有键值对
4.3 代码演示
int main() {
map< string, int>m;
m.insert(map<string, int>::value_type("hi",123));
m.insert(map<string, int>::value_type("hello", 456));
m.insert(map<string, int>::value_type("aa",3));
m.insert(map<string, int>::value_type("nn", 6));
m.insert(map<string, int>::value_type("dd", 8));
m.insert(map<string, int>::value_type("bb", 1));
for (auto it = m.begin(); it != m.end(); ++it) {
cout << it->first << ":" << it->second << " "; //aa:3 bb:1 dd:8 hello:456 hi:123 nn:6
}
// ------------- 1. m.erase(iter);
auto itor_next=m.erase(m.begin());
cout << "itor_next=" << itor_next->first << ":" << itor_next->second << endl; // itor_next=bb:1
for (auto it = m.begin(); it != m.end(); ++it) {
cout << it->first << ":" << it->second << " "; // bb:1 dd:8 hello:456 hi:123 nn:6
}
// ------------- 2. m.erase(begin_iter, end_iter);
auto itor_next1 = m.erase(++m.begin(),--m.end());
cout << "itor_next1=" << itor_next1->first << ":" << itor_next1->second << endl; // itor_next1=nn:6
for (auto it = m.begin(); it != m.end(); ++it) {
cout << it->first << ":" << it->second << " "; // bb:1 nn:6
}
// ------------- 3. m.erase(key);
map< string, int>m1;
m1.insert({ "kkkk",1 });
m1.insert({ "llll",2 });
m1.insert({ "JJJJ",3 });
m1.insert({ "iii",4 });
for (auto it = m1.begin(); it != m1.end(); ++it) {
cout << it->first << ":" << it->second << " "; // JJJJ:3 iii:4 kkkk:1 llll:2
}
int num= m1.erase("llll");
cout << num<< endl; // 1
for (auto it = m1.begin(); it != m1.end(); ++it) {
cout << it->first << ":" << it->second << " "; // JJJJ:3 iii:4 kkkk:1
}
// ------------- 4. 删除满足某个条件的map键值对 erase(it++);
map< string, int>m2;
m2.insert({ "kkkk",1 });
m2.insert({ "llll",2 });
m2.insert({ "JJJJ",3 });
m2.insert({ "iii",4 });
for (auto it = m2.begin(); it != m2.end(); ++it) {
cout << it->first << ":" << it->second << " "; // JJJJ:3 iii:4 kkkk:1 llll:2
}
for (auto it = m2.begin(); it != m2.end(); ) {
if (it->first == "JJJJ") {
m2.erase(it++); // 防止迭代器失效
cout << "删除成功,下一个元素是:" << it->first << ":" << it->second << endl;
//输出: 删除成功,下一个元素是:iii:4
}
else {
++it;
}
}
for (auto it = m2.begin(); it != m2.end(); ++it) {
cout << it->first << ":" << it->second << " "; // iii:4 kkkk:1 llll:2
}
return 0;
}
5、改
5.1 直接修改:Map[key]=value;
5.2 swap() 交换两个map
int main() {
map< string, int>m1;
m1.insert({ "****",1 });
m1.insert({ ")))",2 });
m1.insert({ "&&&&",3 });
m1.insert({ "@@@@",4 });
map< string, int>m2;
m2.insert({ "kkkk",1 });
m2.insert({ "llll",2 });
m2.insert({ "JJJJ",3 });
m2.insert({ "iii",4 });
swap(m1, m2);
for (auto it = m1.begin(); it != m1.end(); ++it) {
cout << it->first << ":" << it->second << " "; // JJJJ:3 iii:4 kkkk:1 llll:2
}
for (auto it = m2.begin(); it != m2.end(); ++it) {
cout << it->first << ":" << it->second << " "; // &&&&:3 ))):2 ****:1 @@@@:4
}
return 0;
}
6、查
切记不要用int value=Map[key];这样会在Map中增加这个key,而value就是缺省值(int 为0,string为空字符串)。
lower_bound() 返回键值>=给定元素的第一个位置
upper_bound() 返回键值>给定元素的第一个位置
value_comp() 返回比较元素value的函数
6.1 [ ]
m[i]
使用 [] 操作符获取 key 为 i 元素的 value
6.2 at()
m.at(i)
使用 at 方法获取 key 为 i 元素的 value C++11
6.3 map的遍历
(*it).first
使用迭代器获取元素的 key
(*it).second
使用迭代器获取元素的 value
//迭代,根据key排序的,我的key是string,故是字典序排序,从a-z
map< string,int>::iterator iter;
for(iter = maps.begin(); iter != maps.end(); iter++)
cout<< iter->first << ' ' << iter->second << endl;//输出的是key value值
//数组形式的遍历
int nSize = maps.size();
for(int index = 0; index < nSize; index++)
cout << maps[index] << endl;
【注意】
如果key不是string类型,则输出不是插入的数据,要注意;
如果key是string类型,输出就是插入的数据(升序输出);
int main() {
//++++++++++++++++++++++++++++ 1.map<int, string> m1;
map<int, string> m1;
m1[9] = "张三";
m1[10] = "李四";
//********* 数组法遍历
for (size_t i = 0; i < m1.size(); ++i) {
cout << m1[i] << " "; //( 空 )张三 李四
}
cout << endl;
//*********迭代器遍历
for (auto it = m1.begin(); it != m1.end(); ++it) {
cout << it->first << ":" << it->second << " "; // 0: 1: 2: 3: 4: 5: 6: 7: 8: 9:张三 10:李四
}
//++++++++++++++++++++++++++++ 2. map<char, string> m2;
map<char, string> m2;
m2['s'] = "张三";
m2['f'] = "李四";
//********* 数组法遍历
for (size_t i = 0; i < m2.size(); ++i) {
cout << m2[i] << " "; // 李四 张三
}
//*********迭代器遍历
cout << " ---------------------------"<<endl;
for (auto it = m2.begin(); it != m2.end(); ++it) {
cout << it->first << ":" << it->second << " ";
// 输出:
// : : : : : : : : : :
// : : : : : : : : : : : : : : : : : : : : !: ": #: $: %: &: ': (: ): *: +: ,: -: .: /: 0: 1: 2: 3: 4: 5: 6: 7: 8: 9: :: ;: <: =: >: ?: @: A: B: C: D: E: F: G: H: I: J: K: L: M: N: O: P: Q: R: S: T: U: V: W: X: Y: Z: [: \: ]: ^: _: `: a: b: c: d: e: f:李四 g: h: i: j: k: l: m: n: o: p: q: r: s:张三
}
//----------------------1、map<string, int> m3;
map<string, int> m3;
m3.insert(pair<string, int>("bb", 2));
m3.insert(pair<string, int>("aa", 8));
m3.insert(pair<string, int>("ff", 0));
m3.insert(pair<string, int>("ee", -4));
cout << endl<< "_________________________" << endl;
for (auto it = m3.begin(); it != m3.end(); ++it) {
cout <<it->first << ":" << it->second << " "; // aa 8 bb 2 ee -4 ff 0
}
//----------------------1、map<string, string> m4;
map<string, string> m4;
m4.insert(pair<string, string>("bb", "张三"));
m4.insert(pair<string, string>("aa", "李四"));
m4.insert(pair<string, string>("ff", "王五"));
m4.insert(pair<string, string>("ee", "LIBSD"));
cout << endl << "_________________________" << endl;
for (auto it = m4.begin(); it != m4.end(); ++it) {
cout << it->first << ":" << it->second << " "; //aa:李四 bb:张三 ee:LIBSD ff:王五
}
return 0;
}
6.4 判断key是否存在
6.4.1 count()
- int num = my_map.count(key);
- 返回值返回值是0或1,表示map中某个key出现的次数
6.4.2 find()
- 返回值
是一个迭代器,key存在返回指向该 key 的迭代器,否则返回指向 m.end() 的迭代器 - map<int, string>::iterator iter = my_map.find(key);
map<int, string>::iterator iter = maps.find(1);
if(iter != mapStudent.end())
cout<< "Find, the value is " << iter->second << endl;
6.5 upper_bound(key)
auto it_pos = m.upper_bound(key) 返回 key 大于给定 key 第一个位置的迭代器
6.6 lower_bound(key)
auto it_pos = m.lower_bound(key) 返回 key大于等于给定 key 第一个位置的迭代器
6.7 equal_range(key)
pair<T,T> p = m.equal_range(key)
返回 pair:
- pair::first 为 lower_bound 元素(大于等于)
- pair::second 为 upper_bound 元素(大于)
7、比较
key_comp() 返回比较元素key的函数
m.key_comp() 返回比较元素 key 的 key_compare 对象
m.value_comp() 返回比较元素 value 的 value_compare 对象
8、大小
my_map.size(); //返回map中的键值对个数
max_size()返回可以容纳的最大元素个数
size() 返回map中元素的个数
9、empty()判空
my_map.empty(); //返回map是否为空,返回值为bool