map介绍:
1.map翻译为映射,是STL中的常用容器也是STL的一个关联容器,它提供一对一的数据处理能力。什么是一对一的数据处理能力呢,像我们查字典,我们可以从开头处找到这个单词对应的页数,从而通过页数找到单词,那么页数-单词就形成了一 一对应的关系。
2.一维map的定义为
map< typename1,typename2 > name,
其中,typename1是映射前的类型(键key),typename2是映射后的类型(值value),其中的键和值不同于数组,只能将一种有限的类型映射到另一种有限的类型,像int a[10]就是将int类型映射到int类型,map可以map可以将任何基本类型(包括STL容器)映射到任何基本类型(包括STL容器),当然键和值必须是唯一的。
map的使用范围
1)需要建立字符(串)与整数之间的映射,使用 map 可以减少代码量。
2)判断大整数(比如几千位)或者其他类型数据是否存在,可以把map当布尔型数组使用(哈希表),因为在主函数外部被定义的变量若不赋值,编译器会自动赋值为0.
3)字符串与字符串之间的映射。
定义以及访问
定义:要使用map,必须先添加map头文件,即#include < map>,
同时必须要有“using namespace std”。
定义一个一维map的方法为:map<typename1,typename2> name;
其中在建立map的同时,会自动按照键(key)的顺序排序。
访问:
访问 map 的元素有两种方式,一种是通过下标访问;另一种是通过迭代器访问。
通过下标访问就像普通的数组元素访问,例如先定义map<sring,int> mp,然后就可以通过mp[break]的方式来访问它对应的元素,如mp[break]=123。
通过迭代器访问,先作如下定义:
map<string,int>vis;
map<string,int>::iterator it;
使用迭代器遍历map的时候,迭代器起始的位置是首元素,但是迭代器的末尾位置是最后一个元素的后一位,所以我们不可以这样写:
for(it=vis.begin();it<=vis.end();it++)
而是要这样写
for(it=vis.begin();it!=vis.end();it++)
相当于一个左闭右开的区间。
我们用“it->first”来访问键,使用“it->second”来访问值。
map常用的函数:
(1).find()和 .size()
find(key)是返回键为 key 的映射的迭代器,时间复杂度为 0(log 2 n),n 为 map 中映射的对数。size()用来获得map中映射的对数,时间复杂度为O(1)。
(2).clear()
clear()用来清空 map,时间复杂度为 0(n)。
(3).erase()
erase()可以删除单个元素,也可以删除一个区间内的所有元素。
删除单个元素可以用:erase(it),it为要删除的元素的迭代器,时间复杂度为O(1)。
也可以用:erase(key),key为要删除的映射的键,时间复杂度为O(log2n)。
删除一个区间内的所有元素用:erase(first,last),first为区间的起始迭代器,last为区间的末尾迭代器的下一个地址,也就是左闭右开的区间[first,last),时间复杂度为O(last-first)。
Pair介绍:
pair 是“二元结构体”的替代品,将两个元素捆绑在一起,节省编码时间。相当于以下定义:
struct pair
{
typename1 first;
typename2 second;
}
Pair的定义及使用
定义:
要使用pair,必须先添加头文件,
即#include < utility >,
同时必须要有“using namespace std”。
因为map的内部实现中涉及pair,因此添加map头文件时会自动添加utility头文件,此时可以省去utility头文件。
pair有两个参数,分别对应first和second的数据类型,可以是任意基本数据类型或者容器。
定义一个pair的方法为:
pair<typename1,typename2> name;
取出pair第一个元素的方法:name.first;
取出pair第二个元素的方法:name.scond;
在这里和map的是不同的!!!
其中pair会自动按照第一个元素从小到大的顺序排序,如果第一个元素的值相同,则会按照第二个元素从小到大的顺序排序。
map的二维表示和迭代器遍(正序/逆序)
1.map与pair嵌套,用pair的二元结构做键。
2.map与map嵌套,创造一个类似于二维数组的map。
示例1:示例来自nefu_ljw
https://blog.csdn.net/ljw_study_in_CSDN/article/details/104355672
using namespace std;
typedef long long ll;
ll n,x,y;
map<pair<ll,ll>,int>vis;
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>x>>y;
vis[{x,y}]++;//结构体当下标
}
printf("\n正向遍历\n");
map<pair<ll,ll>,int>::iterator it;
for(it=vis.begin();it!=vis.end();it++)//正向遍历
printf("%lld %lld %d\n",it->first.first,it->first.second,it->second);
//输出x,y,{x,y}出现次数
printf("反向遍历\n");
map<pair<ll,ll>,int>::reverse_iterator re_it;//注意反向遍历写的是reverse_iterator
for(re_it=vis.rbegin();re_it!=vis.rend();re_it++)//反向遍历
printf("%lld %lld %d\n",re_it->first.first,re_it->first.second,re_it->second);
//输出x,y,{x,y}出现次数
return 0;
}
————————————————
版权声明:本文为CSDN博主「nefu_ljw」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ljw_study_in_CSDN/article/details/104355672
示例2:示例来自nefu_ljw
https://blog.csdn.net/ljw_study_in_CSDN/article/details/104355672
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
map<ll,map<ll,int> >vis;
ll n,x,y;
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>x>>y;
vis[x][y]++;
}
map<ll,map<ll,int> >::iterator i;
map<ll,int>::iterator j;
printf("\n正向遍历\n");
for(i=vis.begin();i!=vis.end();i++)
for(j=i->second.begin();j!=i->second.end();j++)
printf("%lld %lld %d\n",i->first,j->first,j->second);
map<ll,map<ll,int> >::reverse_iterator re_i;
printf("反向遍历\n");
for(re_i=vis.rbegin();re_i!=vis.rend();re_i++)//i需要倒序,j不需要
for(j=re_i->second.begin();j!=re_i->second.end();j++)
printf("%lld %lld %d\n",re_i->first,j->first,j->second);
return 0;
}
————————————————
版权声明:本文为CSDN博主「nefu_ljw」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ljw_study_in_CSDN/article/details/104355672