题目描述
上海闵行膜法学院刚刚结束了高等膜法期中考试,现在有 N ( 0 < N < 1000000) 个学生的成绩需要统计,管理教学的长者们想要知道成绩的总体分布情况,请将不同分数的成绩和人数统计好并分别输出。
输入描述
有多组测试数据,每组测试数据占若干行。
在第 1 行中,有一个数字 N。
在第 2 到第 N + 1 行中,每行一个数字,代表这是一个学生的成绩。
所有数据保证在 32 位有符号整数范围内。
输出描述
每一行的输出格式为:成绩 取得这个成绩的人数。
注意:成绩和取得这个成绩的人数中间有一个空格! 同时,输出的时候。请按成绩的大小从低到高输出
由于数据量较大,请尽量使用时间复杂度较低的排序算法。
样例输入
5
45
45
45
60
60
6
100
60
100
100
50
60
样例输出
45 3
60 2
50 1
60 2
100 3
若是没有接触过STL-map,则很直接会想到用数组或是顺序栈来储存数据,利用 algorithm 中的sort()进行排序。若是遍历到了则相应数据+1,没有遍历到则插入。或者是使用链栈的结构存储。这样就不需要搬动或是交换数据,但是其需要两个值域分别表示成绩与人次,且查找插入也比较麻烦。
由此,有没有一种高效简洁的结构来存储这样一对一的数据呢。这就是STL中的map
map是用来存放
其中key和value可以根据需要来使用。也可以是自定义的结构体或类,甚至可以嵌套另一个map。例如,需要key值为姓名,value为电话号码,那么描述函数就可以写成
map<string,int>info;
这样就声明了一个key为string类型,value为int类型的map容器。
上面说到key值是唯一的,那么即不可能同时满足
info[MFS]==1;
info[MFS]==2;
若存在同时创建了两个key相同的情况,前一个即被覆盖。
使用map需包含map类所在的头文件:
#include
描述函数
Template<class T1, class T2>
map插入有三种方式
1.用insert方法插入pair对象:
info.insert(pairint >("MSF", 1));
2.用insert方法插入value_type对象:
info.insert(map<string, int>::value_type ("MSF", 1));
3.用数组方式插入值:
info["MSF"] = 1;
info["JZM"] = 2;
......
第三种方式存在性能问题。插入”JZM”时,先在info中查找key为”JZM”的元素,没发现,然后将一个新的元素插入info,key是”JZM”,value为空,插入完成后,将value赋为需要的值。 该方法会将每个value都赋为缺省值,然后再赋为需要的值,如果元素是复杂的类或者结构体,则进行了许多无意义的操作,较为浪费时间。而前两种方法可以避免这个问题。
可以使用find()和count()函数来发现一个键是否存在。
对于find()函数,先介绍begin()和end()两个成员函数,分别代表map实例对象中第一个元素和最后一个元素其后的一个位置,函数返回类型是iterator.
map<int, string>::iterator iter;
iter = info.find("JZM");
if(iter != info.end())
{…………/*find*/}
Else
{…………/*can not find*/}
iter是一个iterator类对象。这里的iterator是在template class map中声明的一个类,所以需要用
map<int, string>::iterator iter
来声明一个迭代器iter。
其次介绍count()函数。用count函数来判定关键字是否出现,但其无法定位数据出现位置。由于map一对一的映射关系,就决定了count函数的返回值只有两个,要么是0,要么是1。
清空map中的数据可以用clear()函数,
判定map中是否有数据可以用empty()函数,其返回值类型为bool
1.如果要删除”JZM”,用迭代器删除
map<int, string>::iterator iter;
iter = info.find("JZM");
info.erase(iter);
2.如果要删除“JZM,用关键字删除
int n = info.erase("JZM");
//如果删除了会返回1,否则返回0
3.用迭代器,成片的删除
info.earse(info.begin()+m, info.end()-n);
注:删除区间是一个前闭后开的集合
此处回顾一下map的定义
template < class Key, class T, class Compare = less<Key>,
class Allocator = allocatorconst Key,T> > > class map;
其一共有四个参数,第四个是 Allocator,用来定义存储分配模型。
而第三个参数: class Compare = less
map这里指定less作为其默认比较函数,其实质是对operator()操作符的重载。所以如果不自己指定Compare(),map中键值对就会按照Key的less顺序进行存储。 less是stl里面的一个函数对象,利用定义的 < 运算符进行比较。在我们插入
这也是作为key的类型必须能够进行 < 运算比较【可以通过重载实现】的原因。若不能,则需要自己写比较函数,否则编译报错
这样,若是不想按照定义的 < 运算符进行比较,则可自己加入别的比较函数例如less
template <class T> struct XXX : binary_function bool> {
bool operator() (const T& x, const T& y) const
{return XXX;}
};
至于按照value,暂时我用不到应该。
#include
#include
#include
#include
using namespace std;
int main(){
int n,temp;
map<int,int>dat;
map<int, int>::iterator iter;
while(scanf("%d",&n)!=EOF){
dat.clear();
for(int i=0;iscanf("%d",&temp);
if(dat.count(temp))
dat[temp]++;
else
dat[temp]=1;
}
for(iter = dat.begin(); iter != dat.end(); iter++) {
cout<first<<" "<second<return 0;
}
那天下午刚好看完map然后晚上写题目就用到了。突然兴奋。果然,多了解东西比用已经知道的东西去解决问题有用、有效率。
看到了别的大佬更高效的方法。今晚【2017.11.25】晚上算法组讨论会上听听看,听完了晚上回来再写一个别的吧。
喵呜~