一、简介
map和multimap是键-值对容器,支持根据键进行查找。二者的区别在于后者能够存储重复的键,而前者只能存储唯一的键。
map与multimap插入元素与上一节的容器相似,都会在插入元素时进行排序。
二、基本操作
2.1 头文件
#include <map>
2.2 初始化
初始化map或multimap时,需要指定键和值的类型以及排序函数,排序函数默认是std::less,即升序排列。当然也可以使用自定义的比较函数来实现排序。
#include <map>
#include <string>
using namespace std;
// 降序排列
template <typename T>
struct ReverseSort {
bool operator() (const T& k1, const T& k2) {
return k1 > k2;
}
};
int main() {
// 使用默认排序方式初始化
map<int, string> mapIntToStr1;
multimap<int, string> mmapIntToStr1;
// 使用自定义排序方式初始化
map<int, string, ReverseSort<int>> mapIntToStr2;
multimap<int, string, ReverseSort<int>> mmapIntToStr2;
// 使用复制构造函数初始化
map<int, string> mapIntToStr3(mapIntToStr1);
// 使用迭代器初始化
map<int, string> mapIntToStr4(mapIntToStr1.cbegin(), mapIntToStr1.cend());
return 0;
}
2.3 插入元素
使用insert()函数能够向map或multimap容器中插入元素。insert()函数的具体使用可以按照如下方式:
using namespace std;
map<int, std::string> mapIntToStr1;
mapIntToStr1.insert(make_pair(1, "One"));
mapIntToStr1.insert(pair<int, string>(1, "One"));
2.4 查找元素
使用find()函数能够查找给定键值对应的值,返回一个迭代器。
using namespace std;
// 返回类型为迭代器
map<int, string>::const_iterator pairFound = mapIntToStr1.find(1);
// 对于C++11新增了自动判断类型可以使用auto来简写
auto pairFound = mapIntToStr1.find(1);
if (pairFound != mapIntToStr1.end()) {
cout << pairFound->first << ", " << pairFound->second << endl;
} else {
cout << "Key Not Found" << endl;
}
对于multimap容器,可能包含相同键值对应多个值的情况,可以使用count()来确定有多少个值对应相同的键,而后再对迭代器递增从而访问相邻的值。
auto pairFound = mmapIntToStr.find(1);
if (pairFound != mmapIntToStr.end()) {
size_t numberPairs = mmapIntToStr.count(1);
for (size_t i=0; i<numberPairs; i++) {
cout << pairFound->first << ", " << pairFound->second << endl;
pairFound++;
}
} else {
cout << "Key not found" << endl;
}
2.5 删除元素
使用erase()删除容器中的元素。
// 1. 根据键直接删除, 这将删除multimap中所有键为1的键-值对
mmapIntToStr.erase(1);
// 2. 根据迭代器删除
auto pairFound = mmapIntToStr.find(45);
if (pairFound != mmapIntToStr.end()) {
mmapIntToStr.erase(pairFound);
}
三、基于散列表的STL键-值对容器
unordered_map的平均插入和删除时间是固定的,查找元素的时间也是固定的。unordered_map容器是C++11引入的,与map和multimap差别不大,可以使用类似的方式实现实例化、插入和查找。
但绝对不要编写依赖于unordered_map中元素排列顺序的代码。因为unordered_map是无序的,与map的有序不一样。
在不发生冲突的情况下,unordered_map容器的插入和查找时间几乎是固定的,不受包含的元素数的影响。然而,这并不意味着它优于在各种情形下复杂度都为对数的map容器。在包含的元素不太多的情况下,固定时间可能长的多,导致unordered_map速度比map要慢。
四、总结
需要键-值对唯一时,务必使用map或者unordered_map。但如果键值可能重复时务必使用multimap或者unordered_multimap。如果需要插入和查找时间固定时,务必使用unordered_map或者unordered_multimap。
本章介绍了STL中的map与multimap的用法以及重要成员函数。这些容器插入和查找的时间复杂度为O(logn)。对于unordered_map和unordered_multimap容器,它们的插入和查找性能不受容器大小的影响。