C++: 根据key或value对map排序

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排序

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值