map的默认排序和自定义排序
STL的容器map为我们处理有序key-value形式数据提供了非常大的便利,由于内部红黑树结构的存储,查找的时间复杂度为O(log2N)。
一般而言,使用map的时候直接采取map<typename A, typename B>的形式即可,map的内部实现默认使用A类型变量的升序来排序map的值。
但是有时我们需要对map的值做特殊的排序(不经其他容器的辅助),这就需要在定义map变量时做些特殊的处理。
STL中map的定义是:
template<class _Kty,
class _Ty,
class _Pr = less<_Kty>,
class _Alloc = allocator<pair<const _Kty, _Ty>>>
class map
: public _Tree<_Tmap_traits<_Kty, _Ty, _Pr, _Alloc, false>>
{
这是一个模板类,我们的特殊处理主要改造的就是class _Pr = less<_Kty>,并且从这里我们也能看到,无论做哪种修改,排序都是针对key而言的,要实现value的自定义排序,
不是修改_Pr类型能完成的。
替换_Pr的也必须是一个类型,即至少我们要自己创建一个类型,用来做key的比较。自然,我们需要做的是重载函数调用操作符"()",一般的形式为
class T{
public:
bool operator()(const T& lhs, const T& rhs)const
{
...
}
};
代码需包含头文件<algorithm>、<functional>。
下面是常见的一些自定义排序:
a.对基本类型的key以降序排列
map默认提供的是less<_Kty>类型的排序方式,阅读STL源码
template<class _Ty = void>
struct less
{ // functor for operator<
_CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ty first_argument_type;
_CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ty second_argument_type;
_CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef bool result_type; constexpr bool operator()(const _Ty& _Left, const _Ty& _Right) const
{ // apply operator< to operands
return (_Left < _Right);
}
};
修改上述代码的第10行,为修改后的类型起一个自定义名字很简单,不过STL已经为我们提供了整个类型定义:
template<class _Ty = void>
struct greater
{ // functor for operator>
_CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ty first_argument_type;
_CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ty second_argument_type;
_CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef bool result_type; constexpr bool operator()(const _Ty& _Left, const _Ty& _Right) const
{ // apply operator> to operands
return (_Left > _Right);
}
};
我们直接使用就行:
std::map<int, int, std::greater<int>> mi;
for (int i = ; i < ; i++)
{
mi[i] = i * ;
} std::for_each(mi.begin(), mi.end(),
[](const std::map<int, int, std::greater<int>>::value_type& vl) {
cout << "key:" << vl.first << " value:" << vl.second << '\n';
});
对应的输出为:

这里,我们实现了按key降序排列的目的。
b.为自定义类型的key做排序:
自定义类型的key定义map时(使用map默认排序),我们一般都要做一件事:为自定义类型重载“<”操作符,显然,这是为了map创建对象时可以使用less。
因此,我们替换less<_Kty>也同样是要做这样的事:自定义排序规则, 比如:
class MyKey {
public:
MyKey(int fidx = , int sidx = )
:m_firstIdx(fidx), m_secondIdx(sidx) {}
int m_firstIdx;
int m_secondIdx;
};
class MyCompare{
public:
bool operator()(const MyKey& lhs, const MyKey& rhs)const
{
if (lhs.m_firstIdx > rhs.m_firstIdx)
{
return true;
}
else if (lhs.m_firstIdx == rhs.m_firstIdx)
{
return lhs.m_secondIdx > rhs.m_secondIdx;
}
return false;
}
};
class MyCompare2 {
public:
bool operator()(const MyKey& lhs, const MyKey& rhs)const
{
return lhs.m_firstIdx > rhs.m_firstIdx;
}
};
使用MyCompare:
std::map<MyKey, int, MyCompare> mi;
for (int i = ; i < ; i++)
{
mi[MyKey(i * , i)] = i * ;
} std::for_each(mi.begin(), mi.end(),
[](const std::map<MyKey, int, MyCompare>::value_type& vl) {
cout << "key:" << vl.first.m_firstIdx << "-" << vl.first.m_secondIdx << " value:" << vl.second << '\n';
});
使用MyCompare2:
std::map<MyKey, int, MyCompare2> mi;
for (int i = ; i < ; i++)
{
mi[MyKey(i * , i)] = i * ;
} std::for_each(mi.begin(), mi.end(),
[](const std::map<MyKey, int, MyCompare2>::value_type& vl) {
cout << "key:" << vl.first.m_firstIdx << "-" << vl.first.m_secondIdx << " value:" << vl.second << '\n';
});
以上两种有相同的输出:

我们实现了自定义类型自定义排序的目的。
可以看到,使用map其实有很大的自由度,我们完全可以定制自己的map,为我们解决问题、精简代码带来很大的便利。
map的默认排序和自定义排序的更多相关文章
- MySQL、Oracle、DB2等数据库常规排序、自定义排序和按中文拼音字母排序
MySQL常规排序.自定义排序和按中文拼音字母排序,在实际的SQL编写时,我们有时候需要对条件集合进行排序. 下面给出3中比较常用的排序方式,mark一下 1.常规排序ASC DESC ASC 正序 ...
- Objective-C之NSArray(数组)默认排序与自定义排序
在讲OC中数组的排序之前我先上一段代码,它是简单数组排序的一种方法(也就是元素是字符串或者数据的数组,因为后面要讲元素为类的数组排序) 代码1: NSArray *sortArr4 = [sortAr ...
- EasyUI 数据网格 - 设置排序并自定义排序
数据网格(DataGrid)的所有列可以通过点击列表头来排序.您可以定义哪列可以排序.默认的,列是不能排序的,除非您设置 sortable 属性为 true. 当排序时,数据网格(DataGrid)将 ...
- mysql排序的中文首字母排序和自定义排序
select * FROM organ_new where city_code = 'SZ0755' and organ_type = 'H' and state = '1' ORDER BY FIE ...
- hdu 1263 水果 结构的排序+sort自定义排序
水果 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submissi ...
- Map排序——按key排序,按value排序
注:转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/5959279.html 上一篇博文谈到了集合类的自定义排序方式,那么进一步扩展开来,与集合同等重要的Map有 ...
- MySQL中自定义排序
在开发时候,我们经常使用的是默认的排序规则,但在某些特殊情况下,通过指定顺序来进行排序 -- fileld自定义排序时,应该是非主键的,否则主键是无效 SELECT * FROM customer W ...
- Python自定义排序及我实际遇到的一些题目实例
写在前面,本文主要介绍Python基础排序和自定义排序的一些规则,如果都比较熟悉,可以直接翻到第三节,看下实际的笔试面试题中关于自定义排序的应用. 一.基础排序 排序是比较基础的算法,与很多语言一样, ...
- Python:Base4(map,reduce,filter,自定义排序函数(sorted),返回函数,闭包,匿名函数(lambda) )
1.python把函数作为参数: 在2.1小节中,我们讲了高阶函数的概念,并编写了一个简单的高阶函数: def add(x, y, f): return f(x) + f(y) 如果传入abs作为参数 ...
随机推荐
- Phaser3 对象池随机产生炸弹并销毁
效果图 对象池 Object Pool scene.js /// <reference path="../../libs/phaser/phaser.min.js"/> ...
- 基于Vue实现可以拖拽的树形表格(原创)
因业务需求,需要一个树形表格,并且支持拖拽排序,任意未知插入,github搜了下,真不到合适的,大部分树形表格都没有拖拽功能,所以决定自己实现一个.这里分享一下实现过程,项目源代码请看github,插 ...
- urllib库使用方法 2 parse
import urllib.parse #url.parse用法包含三个方法:quote url, unquote rul, urlencode#quote url 编码函数,url规范只识别字母.数 ...
- 100-Days-Of-ML-Code 评注版(Day 2)
Day2_Simple_Linear_Regression(一元线性回归) 本文引用自 Simple Linear Regression, 对其中内容进行了评注与补充说明. 回归分析是一种预测性的建模 ...
- 最近最少使用算法(LRU)——页面置换
原创 上一篇博客写了先进先出算法(FIFO)——页面置换:http://www.cnblogs.com/chiweiming/p/9058438.html 此篇介绍最近最少使用算法(LRU)——页面置 ...
- Go语言中结构体的使用-第2部分OOP
1 概述 结构体的基本语法请参见:Go语言中结构体的使用-第1部分结构体.结构体除了是一个复合数据之外,还用来做面向对象编程.Go 语言使用结构体和结构体成员来描述真实世界的实体和实体对应的各种属性. ...
- 关于Win10 环境下Quartus II 15.0器件列表无法下拉的解决方法
不知大家在Windows 10 64位系统环境下使用Quartus II 15.0在新建工程时遇到过这种问题没,在新建工程的过程是选择器件的列表无法下拉,只能看到一个器件型号,如图1所示. 图1 开始 ...
- ubuntu下pycharm快捷方式创建
终端输入:sudo gedit /usr/share/applications/Pycharm.desktop 粘贴模板: [Desktop Entry] Type=Application Name= ...
- 20155339 2016-2017-2 《Java程序设计》第4周学习总结
20155339 2016-2017-2 <Java程序设计>第4周学习总结 教材学习内容总结 继承.多态与is-a 继承就是避免多个类间重复定义共同行为. 可以把相同的成粗代码提升为父类 ...
- POI导出excel文件样式
需求: 公司业务和银行挂钩,各种形式的数据之间交互性比较强,这就涉及到了存储形式之间的转换 比如数据库数据与excel文件之间的转换 解决: 我目前使用过的是POI转换数据库和文件之间的数据,下边上代 ...