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的默认排序和自定义排序的更多相关文章

  1. MySQL、Oracle、DB2等数据库常规排序、自定义排序和按中文拼音字母排序

    MySQL常规排序.自定义排序和按中文拼音字母排序,在实际的SQL编写时,我们有时候需要对条件集合进行排序. 下面给出3中比较常用的排序方式,mark一下 1.常规排序ASC DESC ASC 正序 ...

  2. Objective-C之NSArray(数组)默认排序与自定义排序

    在讲OC中数组的排序之前我先上一段代码,它是简单数组排序的一种方法(也就是元素是字符串或者数据的数组,因为后面要讲元素为类的数组排序) 代码1: NSArray *sortArr4 = [sortAr ...

  3. EasyUI 数据网格 - 设置排序并自定义排序

    数据网格(DataGrid)的所有列可以通过点击列表头来排序.您可以定义哪列可以排序.默认的,列是不能排序的,除非您设置 sortable 属性为 true. 当排序时,数据网格(DataGrid)将 ...

  4. mysql排序的中文首字母排序和自定义排序

    select * FROM organ_new where city_code = 'SZ0755' and organ_type = 'H' and state = '1' ORDER BY FIE ...

  5. hdu 1263 水果 结构的排序+sort自定义排序

    水果 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submissi ...

  6. Map排序——按key排序,按value排序

    注:转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/5959279.html 上一篇博文谈到了集合类的自定义排序方式,那么进一步扩展开来,与集合同等重要的Map有 ...

  7. MySQL中自定义排序

    在开发时候,我们经常使用的是默认的排序规则,但在某些特殊情况下,通过指定顺序来进行排序 -- fileld自定义排序时,应该是非主键的,否则主键是无效 SELECT * FROM customer W ...

  8. Python自定义排序及我实际遇到的一些题目实例

    写在前面,本文主要介绍Python基础排序和自定义排序的一些规则,如果都比较熟悉,可以直接翻到第三节,看下实际的笔试面试题中关于自定义排序的应用. 一.基础排序 排序是比较基础的算法,与很多语言一样, ...

  9. Python:Base4(map,reduce,filter,自定义排序函数(sorted),返回函数,闭包,匿名函数(lambda) )

    1.python把函数作为参数: 在2.1小节中,我们讲了高阶函数的概念,并编写了一个简单的高阶函数: def add(x, y, f): return f(x) + f(y) 如果传入abs作为参数 ...

随机推荐

  1. 检测com端口代码实现

    1:scan HRESULT CDevHound::Scan(const vector<CString> &guiInfo, vector<DEV_INFO> & ...

  2. ant-design-pro弹出框表单设置默认值

    项目需求需要使用ant-design-pro的弹出框表单并在表单出现时设置默认值 然而按照官方的示例给 <Input> 标签设置 defaultValue 时发现并没有效果.如下所示: & ...

  3. 20155334 实验四:Android程序设计

    20155334实验四:Android程序设计 实验内容 基于Android Studio开发简单的Android应用并部署测试; 了解Android组件.布局管理器的使用: 掌握Android中事件 ...

  4. day 6 返回值,参数

    1.函数返回值 In [3]: def divid(a,b): ...: shang = a//b ...: yushu = a%b ...: return shang,yushu ...: In [ ...

  5. rem布局注意问题和meta标签

    使用rem前的准备: 如果是移动端,添加name="viewport"的meta标签,其中的属性数值根据实际需求而定: <meta name="viewport&q ...

  6. Drupal views 中合并显示字段

    如图, 需要显示如下数据表格 表格的第三列是由两个字段组成的.分别是title 标题字段和body 内容字段. 默认情况下,一列只显示一个字段.如何同时显示两个呢? 这个问题难不到强大的views,要 ...

  7. Mybatis传递参数的三种方式

    第一种: Dao层使用@Param注解的方法 VersionBox getVersionByVersionNumAndVersionType(@Param("versionNum" ...

  8. Redis主从复制(Master/Slave) 与哨兵模式

    Redis主从复制是什么? 行话:也就是我们所说的主从复制,主机数据更新后根据配置和策略, 自动同步到备机的master/slaver机制,Master以写为主,Slave以读为主 Redis主从复制 ...

  9. 学习HTML 第四节.插入图像

    学习HTML 第四节.插入图像 全是文字的网页太枯燥了吧,我们来搞个图片上去! <!DOCTYPE html><html><head><meta charse ...

  10. python的pip升级问题

    近来由于pip升级为10.0.1了,导致使用pip命令报错,使用过很多方法,最终找到一种相对靠谱的方法,一下是步骤: 进入https://pypi.python.org/pypi/pip 下载pip- ...