map翻译为映射,也是常用的STL容器。众所周知,在定义数组时(如 int array[l00])其实是定义了一个从int型到int型的映射,比如array[0]=25、array[4]=36就分别是将0映射到25、将4映射到36。一个 double型数组则是将int型映射到double型,例如db[0]=3.14,db[1]=0.01。

但是,无论是什么类型,它总是将int型映射到其他类型。这似乎表现出一个弊端:当需要以其他类型作为关键字来做映射时,会显得不太方便。例如有一本字典,上面提供了很多的字符串和对应的页码,如果要用数组来表示“字符串-->页码”这样的对应关系,就会感觉不太好操作。这时,就可以用到map,因为map可以将任何基本类型(包括STL容器)映射到任何基本类型(包括STL容器),也就可以建立 string型到int型的映射。

要使用map,需要添加map头文件,即#include <map> 。除此之外,还需要在头文件下面加上一句:“using namespace std;”。

 

1.map的定义:

map<typename1,typename2> mp;
mp<set<int>, string> mp;

map和其他STL容器在定义上有点不一样,因为map需要确定映射前类型(键key)和映射后类型(值 value),所以需要在内填写两个类型,其中第一个是键的类型,第二个是值的类型。如果是int型映射到int型,就相当于是普通的int型数组。

而如果是字符串到整型的映射,必须使用 string而不能用char数组,因为char数组作为数组,是不能被作为键值的:

map<string, int> mp;

2.map容器内元素的访问:

(1)通过下标访问:

和访问不同的数组是一样的,例如对一个定义为map<char,int> mp的map来说,就可以直接使用mp['c']的方式来访问它对应的整数。但是要注意,map中的键是唯一的。

程序代码:

#include<cstdio>
#include<map>
using namespace std;
int main(){
map<char, int> mp;
mp['a'] = 10;
mp['b'] = 20;
mp['a'] = 30; //10将会被覆盖
printf("%d %d\n",mp['a'],mp['b']);
return 0;
}

运行结果:

map的常用用法详解_#include

(2)通过迭代器访问:

map迭代器的定义:

map<typename1, typename2>::iterator it;

map迭代器使用方法与其他的STL不同,必须能通过一个it来同时访问键和值。(map可以使用it->first来访问键,使用it->second来访问值)。

程序代码:

#include<cstdio>
#include<map>
using namespace std;
int main(){
map<char, int> mp;
for(int i=0;i<5;i++) {
mp['e'-i] = i*10;
}
for(map<char,int>::iterator it=mp.begin();it!=mp.end();it++){
printf("%c %d\n",it->first, it->second);
}
return 0;
}

 

运行结果:

map的常用用法详解_数组_02

map会以键从小到大的顺序自动排序,即按照a<b<c<d<e的顺序排序这三对映射。(map和set内部时使用红黑树实现的)

 

3.map常用函数实例解析:

(1)find()

find(key)返回键为key的映射的迭代器,时间复杂度为O(logN),N为map中映射的个数。

程序代码:

#include<cstdio>
#include<map>
using namespace std;
int main(){
map<char,int> mp;
for(int i=0;i<3;i++) {
mp['a'+i]=i+1;
}
map<char,int>::iterator it = mp.find('b');
printf("%c %d\n",it->first,it->second);
return 0;
}

运行结果:

map的常用用法详解_#include_03

 

(2)erase()

①删除单个元素

  • mp.erase(it),it为需要删除的元素的迭代器,时间复杂度为O(1)

程序代码:

#include<cstdio>
#include<map>
using namespace std;
int main(){
map<char,int> mp;
for(int i=0;i<3;i++) {
mp['a'+i]=i+1;
}
map<char,int>::iterator it = mp.find('b');
mp.erase(it);//删除d 2
for(map<char,int>::iterator it = mp.begin();it!=mp.end();it++)
printf("%c %d\n",it->first,it->second);
return 0;
}

运行结果:

map的常用用法详解_程序代码_04

  • mp.erase(key),key为需要删除的映射的键,时间复杂度为O(logN),N为map内元素的个数。

程序代码:

#include<cstdio>
#include<map>
using namespace std;
int main(){
map<char,int> mp;
for(int i=0;i<3;i++) {
mp['a'+i]=i+1;
}
mp.erase('b');//删除d 2
for(map<char,int>::iterator it = mp.begin();it!=mp.end();it++)
printf("%c %d\n",it->first,it->second);
return 0;
}

 

运行结果:

map的常用用法详解_数组_05

②删除一个区间内的所有元素

mp.erase(first,last),其中first为需要删除的区间的起始迭代器,lat为需要删除的区间的末尾迭代器的下一个地址,也即为删除左闭右开的区间[first,last)。时间复杂度为O(last-first)。

程序代码:

#include<cstdio>
#include<map>
using namespace std;
int main(){
map<char,int> mp;
for(int i=0;i<3;i++) {
mp['a'+i]=i+1;
}
map<char,int>::iterator it = mp.find('b');
mp.erase(it,mp.end());//删除d 2 和其之后的所有映射
for(map<char,int>::iterator it = mp.begin();it!=mp.end();it++)
printf("%c %d\n",it->first,it->second);
return 0;
}

运行结果:

map的常用用法详解_程序代码_06

(3)size()

获取map中映射的对数,时间复杂度O(1)。

程序代码:

#include<cstdio>
#include<map>
using namespace std;
int main(){
map<char,int> mp;
for(int i=0;i<3;i++) {
mp['a'+i]=i+1;
}
printf("%d\n",mp.size());
return 0;
}

 

运行结果:

map的常用用法详解_数组_07

(4)clear()

清空map中的所有元素,复杂度为O(N)。

程序代码:

#include<cstdio>
#include<map>
using namespace std;
int main(){
map<char,int> mp;
for(int i=0;i<3;i++) {
mp['a'+i]=i+1;
}
printf("原元素个数 = %d\n",mp.size());
mp.clear(); //清空map
printf("现元素个数 = %d\n",mp.size());
return 0;
}

 

运行结果:

map的常用用法详解_数组_08

4.map的常见用途:

(1)需要建立字符(或字符串)与整数之间映射的题目,使用map可以减少代码量。

(2)判断大整数或者其他类型数据是否存在的题目,可以把map当bool数组用。

大整数请参考:​​大整数​

                       ​​大整数的四则运算​

(3)字符串和字符串的映射也有可能会遇到。