最近在PAT刷题,其中一道题月饼 (25)需要用到对价格进行排序,但是排序后要用到价格对应的总售价。因而可以考虑用关联容器进行求解,map是比较合适这题的数据结构。
map是用来存放<key, value>键值对的数据结构,可以很方便快速的根据key查到相应的value。关于map的详细定义及用法可以见C++STL之map学习。假如存储学生和其成绩,我们用map来进行存储就是个不错的选择。 我们这样定义map<string, int>,其中学生姓名用string类型,作为Key;该学生的成绩用int类型,作为value。我们可以根据学生姓名快速的查找到他的成绩。另一方面,如果我们想把所有同学和他相应的成绩都输出来,并且按照我们想要的顺序进行输出:比如按照学生姓名的顺序进行输出,或者按照学生成绩的高低进行输出。换句话说,我们希望能够对map进行按Key排序或按Value排序。本文对这两种排序进行一个简单的总结。
一、按Key排序
我们知道,map内部本身就是按序存储的(比如红黑树),这样方便实现快速查找。在我们插入<key, value>键值对时,map就会自动按照key的大小顺序进行存储。因而作为key的类型必须能够进行大小运算的比较。比如int、double、string、char等类型。以月饼 (25)这一题为背景例子进行编程说明。
//按Key排序
#include<iostream>
#include<vector>
#include<map>
#include<iomanip>
using namespace std;
int main()
{
double N,maxneed,tm,ts;
cin>>N>>maxneed;
vector<double> vm,vs,vp;//vm是总量,vs是总销售额,vp是价格
for(int i = 1;i<=N;++i)
{
cin>>tm;
vm.push_back(tm);
}
for(int i = 1;i<=N;++i)
{
cin>>ts;
vs.push_back(ts);
}
for(int i = 0;i<N;++i)
vp.push_back(vs[i]/vm[i]);
map<double,double> m;
for(int i = 0;i<N;++i)
m.insert(make_pair(vp[i],vs[i]));//插入后自动按Key值进行排序
cout<<"按Key排序结果:"<<endl;
for(map<double,double>::iterator it=m.begin();it!=m.end();++it)
cout<<it->first<<" "<<it->second<<endl;
system("pause");
return 0;
}
结果如下:
从结果可以看到未对map进行任何操作,它按照Key值自动进行了排序。
具体到月饼 (25)这一题上,详细分析可以见另外一篇博客PAT上面一道关于“月饼”的题目的解法。
另举一例进行说明:
#include<iostream>
#include<map>
#include<string>
using namespace std;
typedef pair<string, int> PAIR;
ostream& operator<<(ostream& out, const PAIR& p)
{
return out << p.first << "\t" << p.second;
}
int main()
{
map<string, int> name_score_map;
name_score_map["LiMin"] = 90;
name_score_map["ZiLinMi"] = 79;
name_score_map["BoB"] = 92;
name_score_map.insert(make_pair("Bing",99));
name_score_map.insert(make_pair("Albert",86));
for (map<string, int>::iterator iter = name_score_map.begin();
iter != name_score_map.end();
++iter) {
cout << *iter << endl;
}
system("pause");
return 0;
}
结果如下:
上面的按key值排序有个缺点:即当插入的有多个相等的值时,由于key的唯一性,会只保留一个。因此月饼 (25)这一题不适合用按key进行排序求解(因为不排斥某两种月饼的价格相等)。
二、按Value排序
如何实现Map的按Value排序呢?
第一反应是利用STL中提供的sort算法实现,这个想法是好的,不幸的是,sort算法有个限制,利用sort算法只能对序列容器进行排序,就是线性的(如vector,list,deque)。map是一个集合容器,它里面存储的元素是pair,但是它不是线性存储的(像红黑树),所以利用sort不能直接和map结合进行排序。因而可以采用一些其它的思路,总结如下:
思路1:可以考虑将value作为key值进行自动排序。
思路2:可以把map中的key值和value值分别转存到一个pair类型的vector中,在对vector按照一定的规则排序即可。这样的方法对值一样的情况也能够使用。具体代码如下:
//功能:输入单词,统计单词出现次数并按照单词出现次数从多到少排序
#include <iostream>
#include <cstdlib>
#include <map>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int cmp(const pair<string, int>& x, const pair<string, int>& y)
{
return x.second > y.second;
}
void sortMapByValue(map<string, int>& tMap,vector<pair<string, int> >& tVector)
{
for (map<string, int>::iterator curr = tMap.begin(); curr != tMap.end(); curr++)
tVector.push_back(make_pair(curr->first, curr->second));
sort(tVector.begin(), tVector.end(), cmp);
}
int main()
{
map<string, int> tMap;
string word;
while (cin >> word)
{
pair<map<string,int>::iterator,bool> ret = tMap.insert(make_pair(word, 1));
if (!ret.second)
++ret.first->second;
}
vector<pair<string,int>> tVector;
sortMapByValue(tMap,tVector);
for(int i=0;i<tVector.size();i++)
cout<<tVector[i].first<<": "<<tVector[i].second<<endl;
system("pause");
return 0;
}
结果如下:
参考资料