【C艹】关于sort用法之重构cmp(comp)函数的笔记
众所周知,balabalabalabala············。
所以掌握sort函数(库文件:<algorithm>)的用法还是很有必要的。
一般选手只会简单地用用sort排一排数组之类,但是一旦掌握了sort的精髓cmp函数(也有叫comp,名字不重要)的重构,sort函数也可以玩得出神入化。
这里只是不全面地记录下了在切题的过程中遇到的重构cmp的应用,仅供参考:
一、cmp函数的原理探究
研究sort的底层代码就会知道,sort函数非常强大,内部结合了多种排序算法以达到相对稳定的高效。但是不管排序的策略如何,其中都用一个“比较”的步骤。而cmp函数(全称大概代表了单词compare,表示“比较”的意思)便定义了这个比较的标准。
举个栗子:当比较一个数组中a、b(a<b)两个元素的时候,通过cmp函数,我们可以决定a与b比较的结果。比如是小的放在前面(那么比较后a与b的相对位置就是···a···b···(一般sort默认就是非降序)),或者大的放在前面(那么比较后a与b的相对位置就是···b···a···)
怎么把我们对cmp函数的重构应用到sort函数里面呢?
从下面可以看出sort模板有三个参数:
void sort ( RandomAccessIterator first, RandomAccessIterator last ); void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);//排序区间为[first,last)
//注: 随机迭代器,能用此算法的容器是支持随机访问的容器:vector, deque, string。不支持链表一类的排序。
然后我们转到sort的定义找到默认的comp:
// TEMPLATE FUNCTION sort
template<class _RanIt> inline
void sort(_RanIt _First, _RanIt _Last)
{ // order [_First, _Last), using operator<
_STD sort(_First, _Last, less<>());
}
是 less<>(),然后继续转到这个的定义去看:
// TEMPLATE STRUCT less
template<class _Ty = void>
struct less
: public binary_function<_Ty, _Ty, bool>
{ // functor for operator<
bool operator()(const _Ty& _Left, const _Ty& _Right) const
{ // apply operator< to operands
return (_Left < _Right);
}
};
好吧实际上就是个——小于号。
也就是说,比较两个元素a,b的时候,a<b则comp函数返回true;a>=b则comp函数返回false;由默认排序为升序我们可以推知,comp为true的时候a,b顺序不变,!comp为true的时候a,b顺序改变。(只是暂时的推理!!后面发现有坑!!)
为了方便记忆和使用,我们可以这么想:记相对位置分别在左边和右边的两个元素(这里不用a和b表示)为left和right,排序后的left和right的关系是使comp返回true的关系。(但要注意一个特殊情况,left = right的时候comp返回都是false,按照排序的原理比较这两个元素的时候会交换他们的位置,不过交换前后整个数组并无差别,不过这两个元素只会比较一次,所以也不会无限交换下去(后来事实证明我的想法是错误的))
然而事实真的是这样吗?
这时候我写了一个cmp:
bool cmp(int left,int right)
{
return left >= right;
}
当在排序的数组中有两个相同的元素的时候,编译器报了错:

于是我就去查了一下问题的原因,然后知道了sort没有我想的那么简单。
这里引入一个概念:严格弱序(不好意思没找到定义)下文引用自:https://blog.csdn.net/River_Lethe/article/details/78618788?utm_source=blogxgwz3
什么是严格弱序?
C++关联容器的有序容器对元素关键字的类型有要求,元素关键字的类型必须定义了严格弱序(stick weak ordering)
拿内置类型来说,C++都定义了 “<”操作符,这就是一个严格弱序,而“<=”就不是一个严格弱序
严格弱序有什么用?
对于内置类型我们自然可以有<、>、=来判断两个值的大小关系,而对于自定义的类类型,为它定义三种比较操作符是没有必要的,只用一个严格弱序(这里就用<为例)就可以表示两个元素三种大小关系
a小于b
a < b
b小于a
b < a
a等于b
!(a < b) && !( b < a )
严格弱序的三条要求
- 两个关键字不能同时“严格弱序”于对方
- 如果a“严格弱序”于b,且b“严格弱序”于c,则a必须“严格弱序”于c
- 如果存在两个关键字,任何一个都不“严格弱序”于另一个,则这两个关键字是相等的。
如果我们把<代入上面的要求,代替掉“严格弱序”,会发现这三条要求简直是理所当然的,这是因为<正是严格弱序的。反之,如果代入<=就会发现逻辑上的错误:
1.两个关键字不能同时“<=”于对方
显然有a<=b,b<=a,a,b相等时成立
2.如果存在两个关键字,任何一个都不“<=”于另一个,则这两个关键字是相等的。
a不小于等于b,且b也不小于等于a,也就是a>b且b>a,这明显是一个伪命题
然后是报错的原因以及解决办法,参考:
https://www.cnblogs.com/hi3254014978/p/11451901.html
和
https://www.cnblogs.com/RookieSuperman/p/12375563.html
而有时,我们所比较的元素并不仅仅是一个值,还可以是一个结构,一个类的实例,或者排序的策略并不想要升序,这时候就要我们自己重构一下cmp函数了。
二、应用
1、非升序排序(int)
#include <algorithm>
#include <iostream>
using namespace std;
bool cmp(int left,int right)
{
return left > right;
}
int main()
{
int a[] = { , , -, -, , , };
sort(a, a + ,cmp);
for (int i = ; i < ; ++i)
{
cout<<a[i]<<' ';
}
system("pause");
return ;
}
2.结构体排序(多级排序)
#include<iostream>
#include<algorithm>
using namespace std;
struct node{
int a;
int b;
}nodes[] = { {,}, {,}, {,}, {,}, {,} };
bool cmp(const node left,const node right)//排序规则:按a 从大到小,若a相等,则按b从大到小
{
if (left.a == right.a)
{
return left.b > right.b;
}
else
{
return left.a > right.a;
}
}
int main()
{
sort(nodes, nodes + , cmp);
for (int i = ; i < ; ++i)
{
cout << "第" << i + << "个:" << nodes[i].a << "," << nodes[i].b<< endl;
}
system("pause");
return ;
}
3.类实例排序(和同结构体差不多就不写了)
·····························
未完待续,遇到有意思的我会再加上去
【C艹】关于sort用法之重构cmp(comp)函数的笔记的更多相关文章
- 转载 从最简单的vector中sort用法到自定义比较函数comp后对结构体排序的sort算法
转载自:http://www.cnblogs.com/cj695/p/3863142.html sort函数在使用中非常好用,也非常简单,而且效率与冒泡或者选择排序不是一个数量级.本文就sort函数在 ...
- 【转】 从最简单的vector中sort用法到自定义比较函数comp后对结构体排序的sort算法
sort函数在使用中非常好用,也非常简单,而且效率与冒泡或者选择排序不是一个数量级.本文就sort函数在vector中的用法分为sort函数入门用法与自定义comp比较函数比较结构体这两个最基本的功能 ...
- 从最简单的vector中sort用法到自定义比较函数comp后对结构体排序的sort算法
sort函数在使用中非常好用,也非常简单,而且效率与冒泡或者选择排序不是一个数量级.本文就sort函数在vector中的用法分为sort函数入门用法与自定义comp比较函数比较结构体这两个最基本的功能 ...
- 【C++】从最简单的vector中sort用法到自定义比较函数comp后对结构体排序的sort算法
sort函数在使用中非常好用,也非常简单,而且效率与冒泡或者选择排序不是一个数量级.本文就sort函数在vector中的用法分为sort函数入门用法与自定义comp比较函数比较结构体这两个最基本的功能 ...
- c++ 中的sort用法
别人写的,我拿来做做笔记 sort函数的用法 做ACM题的时候,排序是一种经常要用到的操作.如果每次都自己写个冒泡之类的O(n^2)排序,不但程序容易超时,而且浪费宝贵的比赛时间,还很有可能写错.ST ...
- 【算法笔记】B1005 继续(3n+1)猜想+sort()用法
1005 继续(3n+1)猜想 (25 分) 卡拉兹(Callatz)猜想已经在1001中给出了描述.在这个题目里,情况稍微有些复杂. 当我们验证卡拉兹猜想的时候,为了避免重复计算,可以记录下递推过程 ...
- (转) linux之sort用法
sort命令是帮我们依据不同的数据类型进行排序,其语法及常用参数格式: sort [-bcfMnrtk][源文件][-o 输出文件] 补充说明:sort可针对文本文件的内容,以行为单位来排序. 参 数 ...
- sort用法
一.sort用法sort将文件的每一行作为一个单位,相互比较,比较原则是从首字符向后,依次按ASCII码值进行比较,最后将他们按升序输出.vim 1.txt 1:datadir=/aaa/zzz:2: ...
- Linux命令之sort用法
linux之sort用法 sort命令是帮我们依据不同的数据类型进行排序,其语法及常用参数格式: sort [-bcfMnrtk][源文件][-o 输出文件] 补充说明:sort可针对文本文件的内 ...
随机推荐
- 《JavaScript语言入门教程》记录整理:入门和数据类型
目录 入门篇 js介绍 历史 基本语法 数据类型 概述 null 和 undefined 数值 字符串 对象 函数 数组 本系列基于阮一峰老师的<JavaScrip语言入门教程>或< ...
- Python 字典(Dictionary) items()方法
描述 Python 字典(Dictionary) items() 函数以列表返回可遍历的(键, 值) 元组数组.高佣联盟 www.cgewang.com 语法 items()方法语法: dict.it ...
- PHP date_diff() 函数
------------恢复内容开始------------ 实例 计算两个日期间的差值: <?php$date1=date_create("2013-03-15");$da ...
- PHP ftp_quit() 函数
定义和用法 ftp_quit() 函数关闭 FTP 连接. 语法 ftp_quit(ftp_connection) 参数 描述 ftp_connection 必需.规定要关闭的 FTP 连接. 提示和 ...
- PHP decbin() 函数
实例 把十进制转换为二进制: <?phpecho decbin("3") . "<br>";echo decbin("1" ...
- Python程序设计pdf|网盘下载内附提取码
点击此处下载提取码:5o7z 本书提出了以理解和运用计算生态为目标的Python语言教学思想,不仅系统讲解了Python语言语法,同时介绍了从数据理解到图像处理的14个Python函数库,向初学Pyt ...
- 省选模拟赛 4.26 T1 dp 线段树优化dp
LINK:T1 算是一道中档题 考试的时候脑残了 不仅没写优化 连暴力都打挂了. 容易发现一个性质 那就是同一格子不会被两种以上的颜色染.(颜色就三种. 通过这个性质就可以进行dp了.先按照左端点排序 ...
- 2019 HL SC day4
自闭场本来 以为 顶多一些不太会 结果发现 一堆不太会 . 树状数组 感觉 好久没看 了有点遗忘 不过还好 现在我来了.莅临之神将会消灭一切知识点哦. 今天说点不一样东西 树状数组 hh 很有用的东 ...
- 开源后端数据校验插件Validate.Net,类似Validate.js
介绍 Validate.Net将Validate.js移植到.Net平台,可以更方便.更快捷的校验实体内属性值是否合法.内置多种常规数据校验规则(校验必填.校验字符串长度区间.校验最大最小值.校验值区 ...
- What is 测试金字塔?
我的女朋友是一名测试工程师,但她之前却不知道测试金字塔的概念,为此我曾经在家里的白板上画了一个图一层一层给她讲解过.我和同事在给团队面试测试和开发岗位时,也会必问到这个问题,想到可能有很多开发童鞋都不 ...