map的默认排序和自定义排序

STL的容器map为我们处理有序key-value形式数据提供了非常大的便利,由于内部红黑树结构的存储,查找的时间复杂度为O(log2N)。

一般而言,使用map的时候直接采取map<typename A, typename B>的形式即可,map的内部实现默认使用A类型变量的升序来排序map的值。

但是有时我们需要对map的值做特殊的排序(不经其他容器的辅助),这就需要在定义map变量时做些特殊的处理。

STL中map的定义是:

1 template<class _Kty,
2     class _Ty,
3     class _Pr = less<_Kty>,
4     class _Alloc = allocator<pair<const _Kty, _Ty>>>
5     class map
6         : public _Tree<_Tmap_traits<_Kty, _Ty, _Pr, _Alloc, false>>
7     {    

这是一个模板类,我们的特殊处理主要改造的就是class _Pr = less<_Kty>,并且从这里我们也能看到,无论做哪种修改,排序都是针对key而言的,要实现value的自定义排序,

不是修改_Pr类型能完成的。

替换_Pr的也必须是一个类型,即至少我们要自己创建一个类型,用来做key的比较。自然,我们需要做的是重载函数调用操作符"()",一般的形式为

1 class T{
2 public:
3     bool operator()(const T& lhs, const T& rhs)const
4     {
5         ...
6     }
7 };

代码需包含头文件<algorithm>、<functional>。

下面是常见的一些自定义排序:

a.对基本类型的key以降序排列

  map默认提供的是less<_Kty>类型的排序方式,阅读STL源码

 1 template<class _Ty = void>
 2     struct less
 3     {    // functor for operator<
 4     _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ty first_argument_type;
 5     _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ty second_argument_type;
 6     _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef bool result_type;
 7
 8     constexpr bool operator()(const _Ty& _Left, const _Ty& _Right) const
 9         {    // apply operator< to operands
10         return (_Left < _Right);
11         }
12     };

  修改上述代码的第10行,为修改后的类型起一个自定义名字很简单,不过STL已经为我们提供了整个类型定义:

 1 template<class _Ty = void>
 2     struct greater
 3     {    // functor for operator>
 4     _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ty first_argument_type;
 5     _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ty second_argument_type;
 6     _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef bool result_type;
 7
 8     constexpr bool operator()(const _Ty& _Left, const _Ty& _Right) const
 9         {    // apply operator> to operands
10         return (_Left > _Right);
11         }
12     };

  我们直接使用就行:

 1 std::map<int, int, std::greater<int>> mi;
 2     for (int i = 0; i < 5; i++)
 3     {
 4         mi[i] = i * 2;
 5     }
 6
 7     std::for_each(mi.begin(), mi.end(),
 8         [](const std::map<int, int, std::greater<int>>::value_type& vl) {
 9         cout << "key:" << vl.first << "  value:" << vl.second << ‘\n‘;
10     });

  对应的输出为:

  

  这里,我们实现了按key降序排列的目的。

b.为自定义类型的key做排序:

  自定义类型的key定义map时(使用map默认排序),我们一般都要做一件事:为自定义类型重载“<”操作符,显然,这是为了map创建对象时可以使用less。

  因此,我们替换less<_Kty>也同样是要做这样的事:自定义排序规则,  比如:

 1 class MyKey {
 2 public:
 3     MyKey(int fidx = 0, int sidx = 0)
 4         :m_firstIdx(fidx), m_secondIdx(sidx) {}
 5
 6     int m_firstIdx;
 7     int m_secondIdx;
 8 };
 9
10 class MyCompare{
11 public:
12     bool operator()(const MyKey& lhs, const MyKey& rhs)const
13     {
14         if (lhs.m_firstIdx > rhs.m_firstIdx)
15         {
16             return true;
17         }
18         else if (lhs.m_firstIdx == rhs.m_firstIdx)
19         {
20             return lhs.m_secondIdx > rhs.m_secondIdx;
21         }
22         return false;
23     }
24 };
25
26 class MyCompare2 {
27 public:
28     bool operator()(const MyKey& lhs, const MyKey& rhs)const
29     {
30         return lhs.m_firstIdx > rhs.m_firstIdx;
31     }
32 };

使用MyCompare:

 1 std::map<MyKey, int, MyCompare> mi;
 2     for (int i = 0; i < 5; i++)
 3     {
 4         mi[MyKey(i * 2, i)] = i * 2;
 5     }
 6
 7     std::for_each(mi.begin(), mi.end(),
 8         [](const std::map<MyKey, int, MyCompare>::value_type& vl) {
 9         cout << "key:" << vl.first.m_firstIdx << "-" << vl.first.m_secondIdx << "  value:" << vl.second << ‘\n‘;
10     });

使用MyCompare2:

 1 std::map<MyKey, int, MyCompare2> mi;
 2     for (int i = 0; i < 5; i++)
 3     {
 4         mi[MyKey(i * 2, i)] = i * 2;
 5     }
 6
 7     std::for_each(mi.begin(), mi.end(),
 8         [](const std::map<MyKey, int, MyCompare2>::value_type& vl) {
 9         cout << "key:" << vl.first.m_firstIdx << "-" << vl.first.m_secondIdx << "  value:" << vl.second << ‘\n‘;
10     });

  以上两种有相同的输出:

我们实现了自定义类型自定义排序的目的。

可以看到,使用map其实有很大的自由度,我们完全可以定制自己的map,为我们解决问题、精简代码带来很大的便利。

  

原文地址:https://www.cnblogs.com/stay-alive/p/8215400.html

时间: 2024-09-27 11:36:28

map的默认排序和自定义排序的相关文章

C++中sort排序之自定义排序cmp(入门)

咳咳,第一次写这种博客,介绍一下sort的自定义排序cmp函数: sort和cmp的实现需要的头文件有: #include<algorithm> using namespace std; sor()是C++标准库中的排序函数,使用很方便,传进去数组的起始和结束地址就行,注意是左闭右开,默认的排序是<,从小到大,不过可以自己写一个cmpare()来自定义,下面缩写cmp()函数.cmp()函数的返回值要是bool,核心之处也是比较,因为sort默认是从小到大,所以在cmp如果还是要从小到大

[Excel VBA]自定义排序的三种方法

诸君好,前前期我们聊了VBA编程和数据的常规排序……VBA常用小代码105:Rang对象的排序操作……今天我们再聊下自定义排序……何谓自定义排序,就是按指定的顺序对数据源进行排序呗…… 今一共分享了三种方法.第1种方法是系统自带的OrderCustom,优点是代码简洁,缺点是自定义序列有字符长度限制(255个).第2种方法是字典+数组设置序列号,再使用了辅助列进行排序.优点是不会破坏单元格的形式和结构,比如单元格中存在的公式.背景等.第3种方法是只使用字典+数组,借助简单桶排序的技巧,直接对数据

Spark自定义排序与分区

Spark自定义排序与分区 前言: 随着信息时代的不断发展,数据成了时代主题,今天的我们徜徉在数据的海洋中:由于数据的爆炸式增长,各种数据计算引擎如雨后春笋般冲击着这个时代.作为时下最主流的计算引擎之一 Spark也是从各方面向时代展示自己的强大能力.Spark无论是在数据处理还是数据分析.挖掘方面都展现出了强大的主导能力.其分布式计算能力受到越来越多的青睐.本文将介绍spark的排序以及分区. 一.Spark自定义排序 在spark中定义了封装了很多高级的api,在我们的日常开发中使用这些ap

Hadoop学习之路(7)MapReduce自定义排序

本文测试文本: tom 20 8000 nancy 22 8000 ketty 22 9000 stone 19 10000 green 19 11000 white 39 29000 socrates 30 40000    MapReduce中,根据key进行分区.排序.分组MapReduce会按照基本类型对应的key进行排序,如int类型的IntWritable,long类型的LongWritable,Text类型,默认升序排序   为什么要自定义排序规则?现有需求,需要自定义key类型,

MapReduce 学习4 ---- 自定义分区、自定义排序、自定义组分

1. map任务处理 1.3 对输出的key.value进行分区. 分区的目的指的是把相同分类的<k,v>交给同一个reducer任务处理. public static class MyPartitioner<Text, LongWritable> extends Partitioner<Text, LongWritable>{ static HashMap<String,Integer> map = null; static{ map = new Hash

Java集合框架实现自定义排序

Java集合框架针对不同的数据结构提供了多种排序的方法,虽然很多时候我们可以自己实现排序,比如数组等,但是灵活的使用JDK提供的排序方法,可以提高开发效率,而且通常JDK的实现要比自己造的轮子性能更优化. 一 .使用Arrays对数组进行排序 Java API对Arrays类的说明是:此类包含用来操作数组(比如排序和搜索)的各种方法. 1.使用Arrays排序:Arrays使用非常简单,直接调用sort()即可 int[] arr = new int[] {5,8,-2,0,10}; Array

php多维数组自定义排序 uasort()

php内置的排序函数很多:正反各种排: 常用的排序函数: sort() - 以升序对数组排序rsort() - 以降序对数组排序asort() - 根据值,以升序对关联数组进行排序ksort() - 根据键,以升序对关联数组进行排序arsort() - 根据值,以降序对关联数组进行排序krsort() - 根据键,以降序对关联数组进行排序 基本都能满足需求了:关于这些函数的使用方法就不多啰嗦了: 但是在项目的实际开发中还是会有些更加苛刻的排序需求:今天要介绍的排序函数是: uasort() ua

Hadoop之--&gt;自定义排序

data: 3 33 23 12 22 11 1 --------------------- 需求: 1 12 12 23 13 23 3 package sort; import java.io.IOException; import java.net.URI; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path

java编程排序之自定义类型的集合,按业务需求排序

自定义引用类型放入集合中,按实际业务需求进行排序的两种思路 第一种思路: (1)自定义实体类实现java.lang.Comparable接口,重写public int compareTo(Object obj)方法.自定义业务比较规则 (2)利用java.util.Collections类的静态方法sort(List<自定义类型> list)进行排序(默认升序)或者.自己编写排序工具类.冒泡+compareTo(obj)方法 第二种思路 (1)自己编写业务比较规则类.实体类不用实现任何借口.业