C++: 根据key或value对map排序∞
June 06, 2015 map是c++ STL里built-in的数据结构,其元素为pair,pair.first为map的key,pair.second为map的value。
由于map是集合容器,而非序列容器(像vector,list,queue等),所以我们并不能直接用stl里的sort对map进行排序。
下面我们分别讨论根据key和value对相应的map排序。
根据map的key排序
根据key的大小默认排序
map默认是按照的key的大小进行排序的,所以作为map的key必须能够进行<比较。示例说明:
#include <iostream> #include <map> #include <string> using namespace std; void printMap(map<string,int> &m){ map<string, int>::iterator it; for(it = m.begin(); it != m.end(); ++it){ cout<<it->first<<" : "<<it->second<<endl; } } int main(){ map<string,int> m; m["Hello"] = 100; m["World"] = 34; m["C++"] = 12; m.insert(pair<string,int>("Java",23)); m.insert(make_pair("Python",99)); printMap(m); return 0; }
输出结果为:
C++ : 12 Hello : 100 Java : 23 Python : 99 World : 34
自定义key排序方式
默认是按照key由小到大排的序,我们如何自定义排序方式呢?
先看map在stl里面的定义:
template < class Key, class T, class Compare = less<Key>, class Allocator = allocator<pair<const Key,T> > > class map;
前两个为key,value,第三个称之为函数对象。
所谓的函数对象:即调用操作符的类,其对象常称为函数对象(function object),它们是行为类似函数的对象。表现出一个函数的特征,就是通过“对象名+(参数列表)”的方式使用一个类,其实质是对operator()操作符的重载。
默认使用的是less函数对象,对string而言则是按照字典序排列。当然我们也可以使用另外一个函数对象greater。示例如下:
#include <iostream> #include <map> #include <string> using namespace std; void printMap(map<string,int, greater<string> > &m){ map<string, int>::iterator it; for(it = m.begin(); it != m.end(); ++it){ cout<<it->first<<" : "<<it->second<<endl; } } int main(){ //use function object: greater map<string,int, greater<string> > m; m["Hello"] = 100; m["World"] = 34; m["C++"] = 12; m.insert(pair<string,int>("Java",23)); m.insert(make_pair("Python",99)); printMap(m); return 0; }
输出结果为:
World : 34 Python : 99 Java : 23 Hello : 100 C++ : 12
当然我们也可以自定义一个函数对象,用以构建我们需要排序的map。例如根据key的长度排序。
#include <iostream> #include <map> #include <string> using namespace std; //build function object struct compByLen{ bool operator()(const string &s1, const string &s2){ return s1.length() < s2.length(); } }; void printMap(map<string,int,compByLen> &m){ map<string, int>::iterator it; for(it = m.begin(); it != m.end(); ++it){ cout<<it->first<<" : "<<it->second<<endl; } } int main(){ //use function object: greater map<string,int, compByLen> m; m["Hello"] = 100; m["World"] = 34; m["C++"] = 12; m.insert(pair<string,int>("Java",23)); m.insert(make_pair("Python",99)); printMap(m); return 0; }
有bug,待修改
根据value排序
我们不能用sort来最map直接排序,但我们可以把map序列化,放到vector,然后进行排序。sort需要制定range的初始结束位置,以及比较方法。具体见示例:
#include <iostream> #include <map> #include <string> #include <vector> using namespace std; void printVec(vector< pair<string,int> > &vec){ vector<pair<string,int> >::iterator it; for(it = vec.begin(); it!= vec.end(); ++it){ cout<<it->first<<" : "<<it->second<<endl; } } bool comp_by_value(pair<string,int> &p1, pair<string,int> &p2){ return p1.second > p2.second; } struct CompByValue{ bool operator()(pair<string,int> &p1, pair<string,int> &p2){ return p1.second > p2.second; } }; int main(){ map<string,int> m; m["Hello"] = 100; m["World"] = 34; m["C++"] = 12; m.insert(pair<string,int>("Java",23)); m.insert(make_pair("Python",99)); //change to a vector vector<pair<string,int> > vec (m.begin(), m.end()); /* map<string, int>::iterator it; vector<pair<string,int> > vec; for(it = m.begin(); it != m.end(); ++it){ vec.push_back(*it); } */ //use compare function sort(vec.begin(),vec.end(),comp_by_value); //use funcion object //sort(vec.begin(),vec.end(),CompByValue()); printVec(vec); return 0; }
sort的比较方法,可以利用提供比较函数comp_by_value或者构建函数对象来实现。二者均可。
关于sortstd::sort
参考:C++ STL中Map的按Key排序和按Value排序