前面我们学习了pair模板类——《初识模板类pair》是为了本节学习map作准备。map作为有序关联式容器,其通过pair模板的形式存储元素,并根据key值(指pair中的first)进行自动排序,排序默认是升序,但我们也可以通过仿函数实现降序排序,值得注意的是,map的键值具有唯一性,不允许出现重复键值。
接下来我们通过代码来了解如何创建map容器:
#include<bits/stdc++.h>//万能头,以效率为中心 #include<string> #include<map>//包含头文件,养成好习惯 /*map初始化 */ using namespace std; void test() { map<int,int> mp1;//直接创建 map<int,int> mp2{{1,1,},{2,2},{3,3},{4,4},{5,5}} ;//初始化列表 map<int,int> mp3(mp2) ;//拷贝构造 map<int,int> mp4; mp4=mp2;//'='运算符重载 } int main(){ test(); return 0; }
代码成功编译,语法正确!
好学的读者并不满足于此,开头我们提到map容器是有序关联式容器,会根据key值自动排序且排序默认是升序,那我们怎么写仿函数来更改排序规则呢?
仿函数相关知识我就不细说了,这里主要通过实操更改map排序规则:
#include<bits/stdc++.h>//万能头,以效率为中心 #include<string> #include<map>//包含头文件,养成好习惯 /*更改map自动排序规则(map默认是升序排序) */ struct mycmp//创建公共类 { bool operator()(int a,int b) const //重载函数调用运算符 { return a>b;//自定义比较规则 } }; using namespace std; void test() { map<int ,string> mp1{{3,"Dptcpp"},{1,"编程问答"},{9,"计算机二级C语言"},{0,"数据结构教程"},{7,"Java教程"}};//建议这样初始化 ,直观具体 /*map会进行升序排序 */ cout << "map会进行升序排序:"; for(map<int,string>::iterator it = mp1.begin();it!=mp1.end();++it) //迭代器遍历 { cout << it->second << " "; } cout << '\n'; /*在容器创建之初就指定排序规则*/ map<int ,string,mycmp> mp2{{3,"Dptcpp"},{1,"编程问答"},{9,"计算机二级C语言"},{0,"数据结构教程"},{7,"Java教程"}};//第三个参数传入仿函数类型 /*map按照仿函数降序排序 */ cout << "map会进行降序排序:"; for(map<int,string>::iterator it = mp2.begin();it!=mp2.end();++it) //迭代器遍历 { cout << it->second << " "; } cout << '\n'; } int main(){ test(); return 0; }
编译结果如下:
仿函数创建分3步:创建公共类,重载函数调用运算符,然后自定义比较规则。通过仿函数我们更改了map的默认排序规则。
map有序关联式容器有很多成员函数,下表将介绍常用成员函数:
成员函数 | 参数 | 功能描述 |
---|---|---|
operator[] | const Key& key | 访问或插入元素。如果key不存在,会插入默认值并返回引用 |
insert() | const value_type& value | 插入键值对。返回pair<iterator, bool>,bool表示是否插入成功 |
emplace() | Args&&... args | 原地构造元素,避免拷贝。性能优于insert (C++11) |
find() | const Key& key | 查找指定key,返回迭代器。未找到返回end() |
erase() | const Key& key | 删除指定key的元素。返回删除的元素数量(0或1) |
erase() | iterator position | 删除迭代器指向的元素。返回下一个元素的迭代器 |
count() | const Key& key | 返回指定key的数量。对于map总是返回0或1 |
contains() | const Key& key | 检查是否包含指定key。返回bool (C++20) |
empty() | 无参数 | 检查map是否为空。返回bool |
size() | 无参数 | 返回map中元素的数量 |
clear() | 无参数 | 清空map中的所有元素 |
begin() | 无参数 | 返回指向第一个元素的迭代器 |
end() | 无参数 | 返回指向末尾的迭代器 |
rbegin() | 无参数 | 返回指向第一个元素的反向迭代器 |
rend() | 无参数 | 返回指向末尾的反向迭代器 |
lower_bound() | const Key& key | 返回第一个不小于key的元素的迭代器 |
upper_bound() | const Key& key | 返回第一个大于key的元素的迭代器 |
equal_range() | const Key& key | 返回包含所有key匹配元素的范围[pair<iterator, iterator>] |
at() | const Key& key | 访问指定key的元素,带边界检查。key不存在时抛出异常 |
swap() | map& other | 交换两个map的内容 |
根据该成员函数表,我们简单操作一下map容器:初始化map并通过'[]'访问元素,然后调用size()查看map容器内元素总和。
#include<bits/stdc++.h>//万能头,以效率为中心 #include<string> #include<map>//包含头文件,养成好习惯 /*简单操作map容器 */ using namespace std; void test() { map<int ,string> mp{{0,"Dptcpp"},{1,"编程问答"},{2,"计算机二级C语言"},{3,"数据结构教程"},{4,"Java教程"}};//建议这样初始化 ,直观具体 /*通过'[]'key值遍历map容器*/ cout << "通过'[]'key值遍历map容器: "; for(int i=0;i<5;++i) cout << mp[i]<< " "; cout<<'\n'; cout << "此时map内总计有" << mp.size() << "个元素\n"; } int main(){ test(); return 0; }
编译结果为:
总结:map容器底层是靠pair模板类进行构造的,同时map是有序关联式容器,底层是红黑树,会自动按照key进行升序排列,我们也能通过仿函数更改其排序方式。
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程