C++ STL map的自定义排序

map没有随机迭代器,只有顺序迭代器,所以不能用sort


  1. map按键值Key排序

  • 默认按照less<key>升序排列
#include<iostream>
#include<map>
using namespace std;
int main()
{
    srand((unsigned)time(NULL));
    multimap<int,int>mp;
// multimap第三个参数默认为less<Key>,即 less<int>
    int n;
    cin>>n;
    int a,b;
    for(int i=0; i<n; i++)
    {
        a=rand()%4;
        b=rand()%4;
        //插入
        mp.insert(pair<int,int>(a,b));
    }
    map<int,int>::iterator iter;
    //遍历输出
    for(iter=mp.begin(); iter!=mp.end(); iter++)
        cout<<iter->first<<" "<<iter->second<<endl;
    return 0;
}

输入8,Key升序,Value随机:
1 1
1 1
1 2
2 1
3 3
3 0
3 3
3 2

  • 定义map时,用greater< Key>实现按Key值递减插入数据
multimap<int,int,greater<int> >mp;
//注意<int>后空一格

输入8,Key值降序排列,Value随机:
3 0
3 3
3 1
2 3
2 0
1 0
0 0
0 0

  • 当Key值为自定义的类时
  1. 写一个函数对象1(仿函数)
#include<iostream>
#include<map>
using namespace std;
typedef struct tagIntPlus
{
    int num,i;
}IntPlus;
//自定义比较规则
//注意operator是(),不是<
struct Cmp
{
    bool operator () (IntPlus const &a,IntPlus const &b)const
    {
        if(a.num!=b.num)
            return a.num<b.num;
        else return a.i<b.i;
    }
};
int main()
{
    srand((unsigned)time(NULL));
    //注意此处一定要有Cmp,否则无法排序会报错
    multimap<IntPlus,int,Cmp>mp;
    int n;
    cin>>n;
    int a,b;
    IntPlus intplus;
    for(int i=0; i<n; i++)
    {
        a=rand()%4;
        b=rand()%4;
        intplus.num=a;
        intplus.i=b;
        mp.insert(pair<IntPlus,int>(intplus,i));
    }
    map<IntPlus,int>::iterator iter;
    for(iter=mp.begin(); iter!=mp.end(); iter++)
        cout<<iter->first.num<<" "<<iter->first.i<<" "<<iter->second<<endl;
    return 0;
}

输入8,
结果按Key值的num升序排列,当num值相等时按Key值的i升序排列
当Key值相等时按插入顺序排列
此时虽然表现为按Value值升序排列,但实际上只是插入的顺序巧合而已

Key.numKey.ii【Value】
030
112
116
217
221
305
313
334
  1. 在类里重载小于号<
    注意只重载小于号,不要去重载大于号
    如果想改变为 升 / 降序列,只需改变判断条件即可
typedef struct tagIntPlus
{
    int num,i;
    bool operator < (tagIntPlus const& intplus)const
    {
        //当num不等时
        //前一个对象的num>后一个时返回true,降序排列。
        //反之升序排列
        if(num!=intplus.num)
            return num>intplus.num;
        //当num相等时
        //前一个对象的i<后一个时返回true,升序排列
        else return i<intplus.i;
    }
}IntPlus;

主函数只需将第一种方法中的map中的Cmp去掉即可

multimap<IntPlus,int>mp;

输入8,结果:

Key.numKey.ii【Value】
020
011
015
002
224
333
326
317

  1. map按值Value排序

再次强调不能用sort
只能将map中数据压入能用sort的容器,如vector

#include<iostream>
#include<map>
#include<vector>
#include<algorithm>//sort
using namespace std;

typedef struct tagIntPlus
{
    int num,i;
} IntPlus;

typedef pair<tagIntPlus,int> PAIR;

必须有Cmp。
虽然之后会sort,map的排序并不重要,
但是map输入数据时需要比较Key值,没有会报错

struct Cmp
{
    bool operator () (IntPlus const &a,IntPlus const &b)const
    {
        if(a.num!=b.num)
            return a.num<b.num;
        else return a.i<b.i;
    }
};

map会按键值Key升序排列,Value值无要求


下面才是重点:

bool cmp(PAIR const&a,PAIR const&b)
{
    if(a.first.num!=b.first.num)
        return a.first.num<b.first.num;
    else
    {
        if(a.first.i!=b.first.i)
            return a.first.i<b.first.i;
        else return a.second>b.second;
    }
}

上面需重新定义Key升序排列,否则sort之后仅按Value降序排列,Key值被打乱。

int main()
{
    srand((unsigned)time(NULL));
    multimap<IntPlus,int,Cmp>mp;
    int n;
    cin>>n;
    int a,b;
    IntPlus intplus;
    for(int i=0; i<n; i++)
    {
        a=rand()%4;
        b=rand()%4;
        intplus.num=a;
        intplus.i=b;
        mp.insert(pair<IntPlus,int>(intplus,i));
    }
    map<IntPlus,int>::iterator iter;
    cout<<"排序前:"<<endl;
    for(iter=mp.begin(); iter!=mp.end(); iter++)
        cout<<iter->first.num<<"|"<<iter->first.i<<"|"<<iter->second<<endl;

排序前:

    cout<<"排序后:"<<endl;
    vector<PAIR>vec(mp.begin(),mp.end());
    sort(vec.begin(),vec.end(),cmp);
    int size=vec.size();
    for(int i=0;i<size;i++)
        cout<<vec[i].first.num<<"|"<<vec[i].first.i<<"|"<<vec[i].second<<endl;
    return 0;
}

输入8,结果:

排序前:
Key.numKey.ii【Value】
000
005
012
017
023
134
201
336

排序后:

key肯定都没变,Vaule 如愿降序!

Key.numKey.ii【Value】
005
000
017
012
023
134
201
336

完结撒花★,°:.☆( ̄▽ ̄)/$:.°★


  1. 函数对象:即调用操作符的类,其对象常称为函数对象(function object),它们是行为类似函数的对象。表现出一个函数的特征,就是通过“对象名+(参数列表)”的方式使用一个 类,其实质是对operator()操作符的重载。 ↩︎

  • 24
    点赞
  • 68
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值