STL---map
map()的定义
map 翻译为映射,也是常用的STL容器。众所周知,在定义数组时(如 int array[100]),其实是定义了一个从 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 型的映射。
还可以来看一个情况;这次需要判断给定的一些数字在某个文件中是否出现过。按照正常的思路,可以开一个 bool 型 hashTable[max size],通过判断 hashTable[x]为 true 还是 false 来确定x是否在文件中出现。但是这会碰到一个问题,如果这些数字很大(例如有几千位),那么这个数组就会开不了。
而这时 map 就可以派上用场,因为可以把这些数字当成一些字符串,然后建立 string至 int 的映射(或是直接建立 int 至 int 的映射)。 如果要使用map,需要添加 map 头文件,即#include < map >。除此之外,还需要在头文件下面加上一句∶"using namespace std;",这样就可以在代码中使用map了。下面来看map 的一些常用用法。
单独定义一个map:
map<typename,typename> mp;
map和其他 STL 容器在定义上有点不一样,因为map 需要确定映射前类型(键 key)和映射后类型(值 value),所以需要在<>内填写两个类型,其中第一个是键的类型,第二个是值的类型。如果是 int 型映射到 int型,就相当于是普通的 int 型数组。而如果是字符串到整型的映射,必须使用string 而不能用char数组:
map<string,int> mp;
这是因为 char 数组作为数组,是不能被作为键值的。如果想用字符串做映射,必须用string。
前面也说到,map 的键和值也可以是STL 容器,例如可以将一个 set 容器映射到一个字符串∶
map<set<int>,string> mp;
map容器内元素的访问
map 一般有两种访问方式∶通过下标访问或通过迭代器访问。下面分别讨论这两种访问方式。
(1)通过下标访问
和访问普通的数组是一样的,例如对一个定义为 map<char,int> mp 的map 来说,就可以直接使用 mp[‘c’]的方式来访问它对应的整数。于是,当建立映射时,就可以直接使用mp[‘c’]=20 这样和普通数组一样的方式。但是要注意的是,map中的键是唯一的,也就是说,下面的代码将输出30∶
#include<iostream>
#include<map>
using namespace std;
//map
int main()
{
map<char,int> mp;
mp['c'] = 20;
mp['c'] = 30; // 20被覆盖
cout << mp['c'] << endl;
return 0;
}
输出结果:
30
(2)通过迭代器访问
map 迭代器的定义和其他 STL 容器迭代器定义的方式相同∶
map<typenamel,typename2>::iterator it;
typename1和typename2就是定义 map 时填写的类型,这样就得到了迭代器it。map 迭代器的使用方式和其他 STL 容器的迭代器不同,因为 map 的每一对映射都有两个typename,这决定了必须能通过一个 it 来同时访问键和值。事实上,map可以使用 it->first 来访问键,使用 it->second 来访问值。
#include<iostream>
#include<map>
using namespace std;
//通过迭代器访问
//it -> first访问键
//it -> second访问值
int main()
{
map<char,int> mp;
mp['m'] = 20;
mp['r'] = 30;
mp['a'] = 40;
//it -> first 是当前映射的键
//it -> second是当前映射的值
for(map<char,int>::iterator it = mp.begin(); it != mp.end(); it++)
{
cout << it -> first << " " << it -> second << endl;
}
return 0;
}
输出结果:
a 40
m 20
r 30
接下来似乎发现了一个很有意思的现象:map会以键从小到大的顺序自动排序,即按 a<m<r的顺序排列这三对映射。这是由于map 内部是使用红黑树实现的(set也是),在建立映射的过程中会自动实现从小到大的排序功能。
map常用函数
(1)find()
find(key)返回键为key的映射的迭代器,时间复杂度为O(logN),N为map中映射的个数。
#include<iostream>
#include<map>
using namespace std;
int main()
{
map<char,int> mp;
mp['a'] = 1;
mp['b'] = 2;
mp['c'] = 3;
map<char,int>::iterator it = mp.find('b');
cout << it -> first << " " << it -> second << endl;
return 0;
}
输出结果:
b 2
(2)erase()
erase()有两种用法:删除单个元素,删除一个区间内的所有元素
1、删除单个元素有两种方法
1.1、mp.erase(it),it为需要删除的元素的迭代器,时间复杂度为O(1)
#include<iostream>
#include<map>
using namespace std;
int main()
{
map<char,int> mp;
mp['a'] = 1;
mp['b'] = 2;
mp['c'] = 3;
map<char,int>::iterator it = mp.find('b');
mp.erase(it);
for(map<char,int>::iterator it = mp.begin(); it != mp.end(); it++)
{
cout << it -> first << " " << it -> second << endl;
}
return 0;
}
输出结果:
a 1
c 3
1.2、 mp.erase(key),key为想要删除的映射的键,时间复杂度为O(logN),N为map内元素的个数
#include<iostream>
#include<map>
using namespace std;
int main()
{
map<char,int> mp;
mp['a'] = 1;
mp['b'] = 2;
mp['c'] = 3;
mp.erase('b'); //删除键为b的映射,即 b 2
for(map<char,int>::iterator it = mp.begin(); it != mp.end(); it++)
{
cout << it -> first << " " << it -> second << endl;
}
return 0;
}
输出结果:
a 1
c 3
2、删除一个区间内的所有元素
mp.erase(first,last),其中first为需要删除的区间的起始迭代器,而last则为需要删除的区间的末尾迭代器的下一个地址,也即为删除左闭右开的区间[first,last)
#include<iostream>
#include<map>
using namespace std;
int main()
{
map<char,int> mp;
mp['a'] = 1;
mp['b'] = 2;
mp['c'] = 3;
map<char,int>::iterator it = mp.find('b'); //令it指向键为b的映射
mp.erase(it,mp.end()); //删除it之后的所有映射,即b 2 和c 3
for(map<char,int>::iterator it = mp.begin(); it != mp.end(); it++)
{
cout << it -> first << " " << it -> second << endl;
}
return 0;
}
(3)size()
size()用来获取map中映射的对数,时间复杂度为O(1)
#include<iostream>
#include<map>
using namespace std;
int main()
{
map<char,int> mp;
mp['a'] = 1;
mp['b'] = 2;
mp['c'] = 3;
cout << mp.size() << endl; //3对映射
return 0;
}
输出结果:
3
(4)clear()
clear()用来清空map中的所有元素,复杂度为O(N),其中N为map中元素的个数
#include<iostream>
#include<map>
using namespace std;
int main()
{
map<char,int> mp;
mp['a'] = 1;
mp['b'] = 2;
mp['c'] = 3;
mp.clear(); //清空map
cout << mp.size() << endl;
return 0;
}
输出结果:
0