map(映射)
map(映射)是STL的一个关键容器,其提供了一个一对一的数据处理能力,第一个称为关键字,每个关键字只能在map中出现一次,第二个称为该关键字对应的值,从而实现两个数据的映射,类似于字典(和桶排序很相像,但桶排序只能实现数字与数字之间的联系)。map中元素默认按照键值的升序组织。
map的定义格式
map<typedefname1,typedefname2>mp;
typedefname是键的类型,typedefname2是值的类型
如果是字符串到整型的映射,则使用语句:map<string,int> mp;
map的键和值也可以是STL容器,例如需要将一个set容器映射一个字符串:
map<set<int>,string> mp;
map的元素操作
(1)find(key):返回键为key的映射的迭代器,时间复杂度为O(logN),N为map中映射的个数。
(2)erase():删除map中的元素
(3)size():用来获得map中映射的对数,时间复杂度O(1).
(4)clear():清空map中的所有元素,时间复杂度O(N),N为map中映射的个数。
(5)insert():用于插入元素,要结合pair使用(我本人是不习惯使用map的,老师也不爱用,关于map的,本文不会讲到)。
(ps:这些函数操作我都不咋使用,仅供了解,接下来用的例题也是围绕map的一些简单使用)
map容器内元素的访问
1.通过键值进行下标访问
如:map[10];
2.通过迭代器访问
类似于set,用it指向的first和second成员来实现对指向对象的访问
it->first键,it->second值
例题
林大oj 196 让气球飞吧
Output
输出个数最多的气球的颜色(题目保证个数最多的气球有且仅有一种颜色)
Sample Input
3
green
red
green
5
green
red
blue
red
red
Sample Output
green
red
#include <bits/stdc++.h>
using namespace std;
map<string,int>vis;//键为string,值为int
map<string,int>::iterator it;
int main()
{
int n;
string s,ans;
while(cin>>n)
{
vis.clear();
for(int i=1;i<=n;i++)
{
cin>>s;
vis[s]++;//用法类似与桶排序,方括号里是键
}
int num=0;
for(it=vis.begin();it!=vis.end();it++)//迭代器,这一块的使用好像都没变过。。。
{
if(it->second>num)
{
num=it->second;//it对应的值
ans=it->first;//it对应的键
}
}
cout<<ans<<endl;
}
return 0;
}
林大oj 1604 QWQ和彩色石
Input
第1行输入一个数字n,代表这堆石子的个数
第二行输入n个数,代表n个石子的颜色
保证输入的所有数都不超过100
Output
输出一个数字,代表颜色相同的石子个数的最大值
Sample Input
10
1 3 5 7 9 1 2 3 5 5
Sample Output
3
#include <bits/stdc++.h>
using namespace std;
map<int,int> mp;
map<int,int>::iterator it;
int main()
{
int n,x;
while(cin>>n)
{
for(int i=0;i<n;i++)
{
cin>>x;
mp[x]++;
}
int num=0;
for(it=mp.begin();it!=mp.end();it++)
{
if(it->second>num)//筛选出最大值
{
num=it->second;
}
}
cout<<num<<endl;
}
return 0;
}
这题完全可以使用桶排序来解决,下面是桶排序解法
#include <bits/stdc++.h>
int main()
{
int i,n;
scanf("%d",&n);
int a[n];
int b[101]={0};
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
b[a[i]]++;
}
int max=b[a[0]];
for(i=1;i<n;i++)
{
if(b[a[i]]>max)
max=b[a[i]];
}
printf("%d\n",max);
return 0;
}
林大oj 1676 上网统计
统计每个用户每次浏览了多少个网页。
Input
单组输入。
第 1 行包含两个用 1 个空格隔开的正整数 N(1≤N≤1000)和 M(1≤M≤5000)。
第 2~M+1 行,每行包含 2 个用 1 个空格隔开的字符串,分别表示用户名和浏览的网页名。
Output
共 N 行,每行的第一个字符串是用户名,接下来的若干字符串是这个用户依次浏览的网页名(之间用一个空格隔开)。按照用户名出现的次序排序输出。
Sample Input
5 7
goodstudyer bookshopa
likespacea spaceweb
goodstudyer bookshopb
likespaceb spaceweb
likespacec spaceweb
likespacea juiceshop
gameplayer gameweb
Sample Output
goodstudyer bookshopa bookshopb
likespacea spaceweb juiceshop
likespaceb spaceweb
likespacec spaceweb
gameplayer gameweb
Hint
注意:一个人多次浏览了同一个网页时,不必去重
#include <bits/stdc++.h>
using namespace std;
map<string,vector<string> > mp;//用于将每个用户名映射到浏览的网页名的列表
vector<string> vis;//放用户的名字
map<string,int> st;//记录名字出现状态,类似于桶排序
int main()
{
int n,m;
cin>>n>>m;//输入总用户数 n 和总上网记录数 m
while(m--)
{
string name,net;
cin>>name>>net;
mp[name].push_back(net);//将 net 添加到 mp[name] 中,即将浏览的网页名加入到对应用户的列表中
if(st[name]==0)//从未出现过,是第一次出现
{
vis.push_back(name);//放到存名字的数组里,最后名字出现的先后顺序与输入时相同
st[name]=1;//更新桶,已经记录过的名字后续不再记录
}
}
for(int i=0;i<n;i++)
{
cout<<vis[i];//输出用户名字
for(int j=0;j<mp[vis[i]].size();j++)//遍历 mp[vis[i]] 中的网页名并输出
{
cout<<" "<<mp[vis[i]][j];
}
cout<<endl;
}
return 0;
}
有关于vector(不定长数组)与迭代器的使用,可以看之前写的几篇文章。