C++自定义sort比较函数的四种方法
sort函数:对于容器等进行排序,头文件位于<algorithm>中。
普通:可以在sort的第三个参数传入
- 无参:default = less<>()
- less<>():默认升序
- greater<>():默认降序
另外,可以通过自定义的方式来设置sort()的比较函数
引用:https://bbs.huaweicloud.com/blogs/detail/312149
方式1:传入自定义函数指针,(有人也称为回调函数)
bool cmp2(int a, int b) //从大到小
{
return a > b;
}
sort(num, num + 4, cmp2);
方式2:传入一个包含仿函数的对象
引用: https://zhuanlan.zhihu.com/p/362323211
仿函数:定义一个类,类里面定义了某个方法,将该类的对象作为函数的入参,那么在函数中就能调用这个类中的方法。
或者,定义一个类,类里面重载函数运算符(),将该类的对象作为函数的入参,那么在函数中同样能调用重载符()里面的方法
函数对象的出现是为了代替函数指针的,最明显的一个特点是:可以使用内联函数。而如果使用内联函数的指针,编译器会把它当普通函数对待。另外,函数对象是类封装的,代码不但看起来简洁,设计也灵活,比如还可以用关联,聚合,依赖的类之间的关系,与用到他们的类组合在一起,这样有利于资源的管理(这点可能是它相对于函数最显著的优点了)。
仿函数(Functor)也是 STL 六大模块之一,其余 5 个分别是容器(Container)、算法(Algorithm)、迭代器(Iterator)、适配器(Adapter)和分配器(Allocator)。
class cmp
{
public:
bool operator()(int a, int b) //从小到大
{
return a < b;
}
};
sort(num, num + 4, cmp());
方式3:重载 < 运算符
通常用于自定义数据类型,如结构体和类等。
bool operator< (const Student& s1, const Student& s2)
{
if(s1.age==s2.age)
return s1.name <s2.name;//年龄相同时,按姓名小到大排
else
return s1.age > s2.age; //从年龄大到小排序
}
sort(a,a+n);
方式4:lambda匿名函数
另外,对于规模较小的比较函数,lambda有时是一个更简洁的选择。
//lambda表达式定义排序规则
sort(ret.begin(), ret.end(),[](pair<int, int >a, pair<int, int >b)
{ if (a.second != b.second) return a.second < b.second; else return a.first < b.first;});
源代码阅读:sort
template<class _RanIt,
class _Pr> inline
void sort(_RanIt _First, _RanIt _Last, _Pr _Pred)
{ // order [_First, _Last), using _Pred
_DEBUG_RANGE(_First, _Last);
_DEBUG_POINTER(_Pred);
_Sort(_Unchecked(_First), _Unchecked(_Last), _Last - _First, _Pred);
}
// TEMPLATE FUNCTION sort
template<class _RanIt> inline
void sort(_RanIt _First, _RanIt _Last)
{ // order [_First, _Last), using operator<
_STD sort(_First, _Last, less<>());
}
源代码阅读:_Sort
template<class _RanIt,
class _Diff,
class _Pr> inline
void _Sort(_RanIt _First, _RanIt _Last, _Diff _Ideal, _Pr _Pred)
{ // order [_First, _Last), using _Pred
_Diff _Count;
for (; _ISORT_MAX < (_Count = _Last - _First) && 0 < _Ideal; )
{ // divide and conquer by quicksort
pair<_RanIt, _RanIt> _Mid =
_Unguarded_partition(_First, _Last, _Pred);
_Ideal /= 2, _Ideal += _Ideal / 2; // allow 1.5 log2(N) divisions
if (_Mid.first - _First < _Last - _Mid.second)
{ // loop on second half
_Sort(_First, _Mid.first, _Ideal, _Pred);
_First = _Mid.second;
}
else
{ // loop on first half
_Sort(_Mid.second, _Last, _Ideal, _Pred);
_Last = _Mid.first;
}
}
if (_ISORT_MAX < _Count)
{ // heap sort if too many divisions
_STD make_heap(_First, _Last, _Pred);
_STD sort_heap(_First, _Last, _Pred);
}
else if (1 < _Count)
_Insertion_sort(_First, _Last, _Pred); // small
}
注:以上代码来源于引用链接,但是我看了下MSVC C++ 20下的algorithm代码,除了宏命名以外,基本逻辑没有太大区别。
STL库函数的实现是:快速排序 + 堆排序 + 插入排序
首先调用快排,对于数据进行依据pivot的分割,递归调用,
对于较大的数据(_ISORT_MAX < _Count),建立heap堆排序,
对于较小的数据:插入排序
C++自定义sort比较函数的四种方法的更多相关文章
- 织梦DedeCMS模板防盗的四种方法
织梦(DedeCMS)模板也是一种财富,不想自己辛辛苦苦做的模板被盗用,在互联网上出现一些和自己一模一样的网站,就需要做好模板防盗.本文是No牛收集整理自网络,不过网上的版本都没有提供 Nginx 3 ...
- 运行jar应用程序引用其他jar包的四种方法
转载地址:http://www.iteye.com/topic/332580 大家都知道一个java应用项目可以打包成一个jar,当然你必须指定一个拥有main函数的main class作为你这个ja ...
- C#播放声音的四种方法 +AxWindowsMediaPlayer的详细用法
C#播放声音的四种方法 第一种是利用DirectX 1.安装了DirectX SDK(有9个DLL文件).这里我们只用到MicroSoft.DirectX.dll和 Microsoft.Directx ...
- (转载)eclipse插件安装的四种方法
eclipse插件安装的四种方法 Eclipse插件的安装方法 1.在eclipse的主目录(ECLIPSE_HOME, 比如在我的机器上安装的目录是:D:\eclipse)有一个plugins的目录 ...
- iOS-UITextField中给placeholder动态设置颜色的四种方法
思路分析: 0.自定义UITextField 1.设置占位文字的颜色找-->placeholderColor,结果发现UITextField没有提供这个属性 2.在storyboard/xib中 ...
- android中退出当前应用程序的四种方法
android中退出当前应用程序的四种方法 [IT168 技术]Android程序有很多Activity,比如说主窗口A,调用了子窗口B,如果在B中直接finish(), 接下里显示的是A.在B中如何 ...
- Dojo初探之2:设置dojoConfig详解,dojoConfig参数详解+Dojo中预置自定义AMD模块的四种方式(基于dojo1.11.2)
Dojo中想要加载自定义的AMD模块,需要先设置好这个模块对应的路径,模块的路径就是这个模块的唯一标识符. 一.dojoConfig参数设置详解 var dojoConfig = { baseUrl: ...
- mysql insert插入时实现如果数据表中主键重复则更新,没有重复则插入的四种方法
[CSDN下载] Powerdesigner 设计主键code不能重复等问题 [CSDN博客] Oracle中用一个序列给两个表创建主键自增功能的后果 [CSDN博客] MySQL自增主键删除后重复问 ...
- python QQTableView中嵌入复选框CheckBox四种方法
搜索了一下,QTableView中嵌入复选框CheckBox方法有四种: 第一种不能之前显示,必须双击/选中后才能显示,不适用. 第二种比较简单,通常用这种方法. 第三种只适合静态显示静态数据用 第四 ...
- eclipse插件安装的四种方法
Eclipse插件的安装方法 1.在eclipse的主目录(ECLIPSE_HOME,比如在我的机器上安装的目录是:D:\eclipse)有一个plugins的目录,这种方法的插件安装非常简单,只要将 ...
随机推荐
- C# 开发桌面应用简单介绍
一. C#使用场景介绍 C#是微软公司发布的一种由C和C++衍生出来的面向对象的编程语言.运行于.NET Framework和.NET Core(完全开源,跨平台)之上的高级程序设计语言. 二. 开发 ...
- Canvas实现画布的缩放
主要介绍三种方式: 首先创建一个index.html文件 <!DOCTYPE html> <html lang="en"> <head> < ...
- 线段树的区间更新 hdu 1698
***第一次写的果断超时,所以百度了一下,知道我写的每一次都要递归最底层,这样会花费很多时间,第二次写得线段树的区间更新,因为一个条件写错了,真是让我坑到死, 这样区间相同的不必更新,省了很多时间.. ...
- vim处理冲突文件
一.文件冲突前: 二.文件冲突后(默认为): 此时编辑文档,将before改为after但是异常退出了,此时编辑文档提示冲突: 回车进入展示编辑前的文档: ll-a可查看到隐藏文件的信息: 三.文件冲 ...
- 浅谈 Docker 网络:单节点多容器
1.同网段多容器访问 这一节将对 Docker 多容器网络进行讨论,构建容器网络示意图如下:
- Go-方法-method
- [转帖]oceanbase 的简单介绍
English | 中文版 OceanBase Database 是一个分布式关系型数据库.完全由蚂蚁集团自主研发. OceanBase 基于 Paxos 协议以及分布式架构,实现了高可用和线性扩展. ...
- [转帖][译]tcpdump 示例教程
https://colobu.com/2019/07/16/a-tcpdump-tutorial-with-examples/ 目录 [−] 基于IP查找流量 根据来源和目标进行筛选 根据网段进行查找 ...
- [转帖]Linux如何查看网关地址
转至:https://baijiahao.baidu.com/s?id=1733537078943023051&wfr=spider&for=pc 服务器之间的通信是通过ip地址来 ...
- TCP内核参数的简单验证
前言 春节假期时学习了下内核参数与nginx的调优 最近因为同事遇到问题一直没有解,自己利用晚上时间再次进行验证. 这里将几个参数的理解和验证结果简单总结一下. 希望能够在学习的过程中将问题解决掉. ...