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作为参数 ...
随机推荐
- RuntimeError: Cannot run in multiple processes: IOLoop instance has already been initialized. You cannot call IOLoop.instance() before calling start_processes()
解决方法: settings中的debug改为false,或者注释掉 参照: https://stackoverflow.com/questions/32521122/cannot-run-in-mu ...
- STM32(2)——GPIO
对于初学者而言,最简单的是对芯片上的IO进行操作,我们学习ARM时候,第一个工程就是点亮LED,STM32F103ZET6通用输入输出接口(General-Purpose Inputs/Outputs ...
- vue相关理论知识
es6常用语法简介 es是js的规范标准 let 特点: 1.有全局和函数作用域,以及块级作用域(用{}表示块级作用域范围) 2.不会存在变量提升 3.变量不能重复声明 const 特点: 1.有块级 ...
- 双端队列 ADT接口 数组实现
Deque ADT接口 DEQUEUE.h: #include <stdlib.h> #include "Item.h" void DEQUEUEinit(int); ...
- SSM(Spring5.x+Mybatis3)框架搭建【解决日志问题】(Github源码)
闲来无事,用SSM写个小东西,发现spring已经迭代到5.x了,遂出此文,希望对各位同学有些许帮助. IDE:idea OS:windows 源代码:https://github.com/JHeav ...
- (数据科学学习手札48)Scala中的函数式编程
一.简介 Scala作为一门函数式编程与面向对象完美结合的语言,函数式编程部分也有其独到之处,本文就将针对Scala中关于函数式编程的一些常用基本内容进行介绍: 二.在Scala中定义函数 2.1 定 ...
- IDEA下安装与使用Junit4
安装Junit4 打开File->Settings->Plugins,单击下图所示按钮 搜索JunitGeneratorV2.0并安装 重启IDEA 打开File->Project ...
- WPF RoutedEvent and HitTest - 简书
原文:WPF RoutedEvent and HitTest - 简书 学习的时候切忌心浮气躁,慢慢的过每一个知识点,不要漏掉任何细节.不然当遇到细节问题的时候,会恼,会闹,会悔不该当初--花一下午调 ...
- NetWork——TCP的流量控制和拥塞控制
,然后开始执行拥塞避免算法,使拥塞窗口缓慢地线性增大. 这里为什么替换掉了慢开始算法呢,这是因为收到重复的ACK不仅仅告诉我们一个分组丢失了,由于接收方只有在收到另一个报文段时才会产生重复的ACK,所 ...
- day6 网络 HTML模板
1.HTML模板 HTML模板 baidu一下 http://www.cssmoban.com/ http://www.cnblogs.com/web-d/archive/2010/04/16/171 ...