c++结构体数组sort排序出错?(关于sort排序comp比较器的严格弱排序性质)

news2024/9/24 15:20:04

文章目录

  • sort的严格弱排序的性质
    • 无效的比较器(Invalid comparator)
    • 正确的比较器

sort的严格弱排序的性质

我在给结构体数组排序的时候,自定义了sort函数的排序法则,我的结构体如下定义:

struct score
{
	int a, b, c;//语数英
	int sum;	//总分
	int num;	//学号
};

排序标准:

  • 首先按照总分排序
  • 总分相同的情况下按照语文成绩a排序
  • 再相同的情况下,按照学号的大小排序,因此经过这三重检测,最后得到的一定是已经排序好的。

无效的比较器!
在这里插入图片描述


原因:参考cplusplus中对于comp比较规则的解析。

comp
Binary function that accepts two elements in the range as arguments, and returns a value convertible to bool. The value returned indicates whether the element passed as first argument is considered to go before the second in the specific strict weak ordering it defines.
The function shall not modify any of its arguments.
This can either be a function pointer or a function object.

即comp必须是一个严格弱排序的性质的比较器。

严格弱排序:(a=50,b=60) a < b

  1. 对于a < b,满足 a < b
  2. 若交换两数: a=60,b=50,此时应该返回false, 60 < 50(不满足,返回false)

比如说我有这样一个例子:

struct A
{
	int num;
};
bool comp(A a, A b)
{
	return a.num >= b.num;
}
A a[2];
a[0].num = 11;	//两个值相等!!!!!
a[1].num = 11;	//会出现比较错误!!!
sort(a, a + 2, comp);

在sort函数比较的时候,它会严格弱排序,比较 a是否 >= b,然后两个对象会进行交换,重新比较一遍,相当于这次比较的是 b是否>= a

  1. a >= b ? 满足: true
  2. b <= a ? 满足: true
  3. 这样就出现了一个冲突,不管是a >= b还是b >= a都会返回true的情况,我们都知道sort中只要comp返回true,两个元素就会交换一次,因此comp返回两次true,会对两个元素交换两次,相当于没有交换,因此就会出现无效的比较器的情况。
  4. 正确的交换方式: 当 == 的时候,他们不用交换就可以了,此时如果两个元素相等,则都返回false,因此两次false,在sort中就不用交换,因此达到了等于时不交换的目标。
bool comp(A a, A b)
{
	return a.num > b.num;	//去除=的判断,
}


再回到本题:

无效的比较器(Invalid comparator)

我们自定义的排序法则如下定义:

  • 首先按照总分排序
  • 总分相同的情况下按照语文成绩a排序
  • 再相同的情况下,按照学号的大小排序,因此经过这三重检测,最后得到的一定是已经排序好的。
bool comp2(struct score sc1, struct score sc2)
{
	//总分高的在前面
	if (sc1.sum > sc2.sum)
	{
		return true;
	}
	//如果总分相同,则a表示语文成绩,语文成绩高的在前面
	if (sc1.a > sc2.a)
	{
		return true;
	}
	//总分和语文成绩都相等,则num学号小的在前面
	if (sc1.num < sc2.num)
	{
		return true;
	}
	return false;
}

然后在我创建变量,并且输入进行排序后

sort(sc + 1, sc + 1 + n, comp2);

严格弱排序,检查两个数分别互换位置的比较情况:

假设我比较的两个数字:

  • sc1 : 2 244(a=84)
  • sc2: 1 237(a=90)
  1. sc1 与 sc2 的检查:首先检查总分: 244>237 ,第一个if满足,返回true。
  2. sc2 与 sc1 的检查(sc1=sc2,sc2=sc1)然后交换两个对象(进行弱排序比较):237 < 244,第一个if不满足,90 > 84,第二个if满足,返回true。
  3. 此时返回了两次true,表明这两个对象要交换两次,但实际上就像等于没交换,但是sort一定要进行一次交换,因此出现 无效的比较器!!

如何解决这个问题呢?


正确的比较器

bool comp1( struct score sc1,   struct score sc2)
{
	//分数高的在前面
	if (sc1.sum > sc2.sum)
	{
		return true;
	}
	//如果总分一样,则语文成绩大的在前面
	if (sc1.sum == sc2.sum && sc1.a > sc2.a)
	{
		return true;
	}
	///如果前两项都一样,则学号小的在前面
	if (sc1.sum == sc2.sum && sc1.a == sc2.a && sc1.num < sc2.num)
	{
		return true;
	}
	//如果都不满足,返回false
	return false;
}

再来比较这两个对象: (我们可以猜测出来,排序后位序(总分): sc2, sc1

  • sc1: 1 237(a=90)
  • sc2 : 2 244(a=84)
  1. sc1 比较 sc2:首先244>237 ,返回true
  2. sc1=sc2 比较 sc2=sc1,交换后比较:237 < 244,第一个if不满足,同时他们的总分不同,无法进入第二个if,也不满足,同理第三个if也不满足,最终返回false。
  3. 一个返回true,一个返回false,满足comp的比较准则,因此sc1与sc2交换,不会产生无效的比较准则,因为在if语句的前面都加上了必须首先不满足前一项的要求,然后才能进行优先级第二的比较准则。

两个比较条件的比较:

//错误的排序比较器
bool compOk(struct score sc1, struct score sc2)
{
	if (sc1.sum > sc2.sum)
	{
		return true;
	}
	if (sc1.a > sc2.a)
	{
		return true;
	}
	if (sc1.num < sc2.num)
	{
		return true;
	}
	return false;
}
//正确的比较器
bool compError( struct score sc1,   struct score sc2)
{
	if (sc1.sum > sc2.sum)
	{
		return true;
	}
	if (sc1.sum == sc2.sum && sc1.a > sc2.a)
	{
		return true;
	}
	if (sc1.sum == sc2.sum && sc1.a == sc2.a && sc1.num < sc2.num)
	{
		return true;
	}
	return false;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/130376.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

English Learning - L1-8 时态(上) 2022.12.29 周四

English Learning - L1-8 时态&#xff08;上&#xff09; 2022.12.29 周四8 时态为什么时态难学&#xff1f;什么是时态&#xff1f;如何套用时态表8.1 一般时态核心思维&#xff08;一&#xff09; 一般现在时核心思维用法1. 普遍的事实和真理2. 重复活动&#xff08;习惯&am…

166页7万字智慧工厂可视化解决方案

【版权声明】本资料来源网络&#xff0c;仅用于行业知识分享&#xff0c;供个人学习参考&#xff0c;请勿商用。【侵删致歉】如有侵权请联系小编&#xff0c;将在收到信息后第一时间进行删除&#xff01;完整资料领取见文末&#xff0c;部分资料内容&#xff1a; 第 一 章 应用…

QT VS移植过程中出现的问题以及解决记录

目录 一、无法定位程序输入点于动态链接库 二、E1696 无法打开 源 文件 “QString“ 三、编译Qt项目提示 error MSB6006: “cmd.exe”已退出 四、禁止显示状态 错误 MSB8036 找不到 Windows SDK 五、E2512 功能测试宏的参数必须是简单标识符 六、Qt VS中双击ui文件无法打…

【计算机模型机设计】单周期MIPS CPU设计报告

2022年结束了&#xff0c;过去一年确实发生了很多事情&#xff0c;开心的、伤心的、激动的、平凡的…这些都已经成为过去了&#xff0c;只希望在新的一年里&#xff0c;能够多一些开心&#xff0c;少一些emo&#xff0c;做一些自己喜欢的事情。 其实说实话&#xff0c;感觉我的…

Linux驱动之平台总线

文章目录前言一、什么是平台总线&#xff1f;二、平台总线相关的结构体三、平台总线的注册和注销四、总线平台的框架总结前言 一个完整的驱动程序总是由三部分组成&#xff1a;设备、总线、驱动 设备就好比我们的硬件&#xff1a;比如oled &#xff0c;那么总线就相当于iic总线…

Faster RCNN网络源码解读(Ⅲ) --- 如何搭建自己的数据集

目录 一、如何生成类似pascal voc一样结构的文件&#xff08;split_data.py&#xff09; 二、如何创建属于自己的数据集&#xff08;my_dataset.py&#xff09; 2.1 代码 2.2 代码解释 2.2.1 初始化函数__init__ 2.2.2 parse_xml_to_dict函数&#xff08;解析xml文件&…

35岁程序员还能找到工作吗?60%选择转岗项目经理!

我因为工作关系接触过大把的程序员朋友&#xff0c;知道他们都有35岁年龄焦虑&#xff0c;曾经他们在群里调侃程序员的尽头是开出租车和开饭店。毕竟一个公司的CTO只有一个&#xff0c;随着年龄的增长他们的体力和学新的技术都会明显吃力&#xff0c;慢慢就承受不起失业&#x…

[极客大挑战 2019]Havefun1、EasySQL(BUUCTF)

前言: 这篇文章还是是为了帮助一些 像我这样的菜鸟 找到简单的题解 今天是2022年的最后一天&#xff0c; 这一年我居然写了72篇文章 获得5枚勋章 还多了14个粉丝 好了不说了&#xff0c;上水题的题解 EasySQL题目描述 解题工具: 不需什么工具&#xff0c;如题名easy …

元宇宙产业委员会发布《第一届第六次主任委员会议公报》

2022年12月29日中国移动通信联合会元宇宙产业工作委员会第一届第六次主任委员会议书面召开&#xff0c;共同主席3人、学术指导3人、产业指导3人&#xff0c;联席主任委员3人、执行主任委员4人、常务副主任委员9家/人、副主任委员25家/人均以通信方式出席会议并表决相关事项。 …

深入分析Linux虚拟化KVM-Qemu之ARMv8虚拟化

说明&#xff1a; KVM版本&#xff1a;5.9.1 QEMU版本&#xff1a;5.0.0 工具&#xff1a;Source Insight 3.5&#xff0c; Visio 1. 概述 KVM虚拟化离不开底层硬件的支持&#xff0c;本文将介绍ARMv8架构处理器对虚拟化的支持&#xff0c;包括内存虚拟化、中断虚拟化、I/O虚…

BM33 二叉树的镜像

题目 操作给定的二叉树&#xff0c;将其变换为源二叉树的镜像。 数据范围&#xff1a;二叉树的节点数 0≤n≤1000&#xff0c; 二叉树每个节点的值 0≤val≤1000。 要求&#xff1a; 空间复杂度 O(n)。本题也有原地操作&#xff0c;即空间复杂度 O(1)的解法&#xff0c;时间…

windows系统中安装maven用来编译项目

1为什么要安装maven 作为一个编程小白&#xff0c;我们先看一下以前学java的时候&#xff0c;下载一个项目源码&#xff0c;是不是需要把所依赖的第三方jar包一起跟着源码打包放一起&#xff0c;这样别人的代码才能运行起来。这种方式不利于对jar包的管理&#xff0c;后来就出现…

力扣sql入门篇(三)

力扣sql入门篇(三) 1 修复表中的名字 1.1 题目内容 1.1.1 基本题目信息 1.1.2 示例输入输出 1.2 示例sql语句 SELECT user_id,CONCAT(upper(substring(name,1,1)),lower(substring(name,2,length(name)-1))) name FROM Users ORDER BY user_id;1.3 运行截图 2 按日期分组销…

计算机网络学习笔记(谢希仁版本)

计算机网络学习笔记 1. 概述 1.1 计算机网络在信息时代的作用 互联网基本特点&#xff1a; 连通性&#xff1a;互联网上用户不管距离多远&#xff0c;都能通信&#xff0c;就像这些用户终端都彼此连通 共享性&#xff1a;指资源共享&#xff0c;包含信息、软件、硬件等共享…

WebRTC的拥塞控制技术(Congestion Control)

\1. 概述 对于共享网络资源的各类应用来说&#xff0c;拥塞控制技术的使用有利于提高带宽利用率&#xff0c;同时也使得终端用户在使用网络时能够获得更好的体验。在协议层面上拥塞控制是TCP的一个总要的组成部分&#xff1b;但是对于非面向链接的传输层协议&#xff0c;如UDP&…

智慧城管违规摆摊沿街晾晒识别检测 python

智慧城管违规摆摊沿街晾晒识别检测通过opencvpython对现场画面中进行7*24小时不间断实时监测&#xff0c;当opencvpython城管违规摆摊沿街晾晒识别检测监测到沿街晾晒违规摆摊占道经营时&#xff0c;立即抓拍告警。OpenCV的全称是Open Source Computer Vision Library&#xff…

小侃设计模式(十九)-解释器模式

1.概述 解释器模式&#xff08;Interpreter Pattern&#xff09;是一种使用相对较少的模式&#xff0c;主要使用在编译解释等场景&#xff0c;例如&#xff1a;编译器、规则引擎解释、正则表达式解析等&#xff0c;这些语言又被称为领域特定语言&#xff08;Domain Specific L…

【数据结构与算法】数据结构介绍与稀疏数组相关操作

文章目录一 数据结构介绍1 数据结构和算法的重要性2 数据结构和算法的关系3 线性结构和非线性结构&#xff08;1&#xff09;线性结构&#xff08;2&#xff09;非线性结构二 稀疏数组1 应用场景2 基本概念&#xff08;1&#xff09;基本介绍&#xff08;2&#xff09;压缩策略…

并发编程——1.进程与线程

目录1.进程与线程1.1.概述1.2.并行与并发本文笔记整理来自黑马视频https://www.bilibili.com/video/BV16J411h7Rd/?p1&#xff0c;相关资料可在视频评论区进行获取。 1.进程与线程 1.1.概述 &#xff08;1&#xff09;进程 程序由指令和数据组成&#xff0c;但这些指令要运…

2022 年度作品优秀大赏 | 开发者说·DTalk

岁聿云暮之际&#xff0c;回首 2022&#xff0c;开发者们一直在迈着坚定的步伐向顶峰攀登&#xff0c;我们也竭尽所能不断为大家提供帮助——操作系统 Android 13 完成 Beta 版到正式版的蜕变&#xff0c;开发工具 Flutter 3.3 全力支持您的跨平台之旅&#xff0c;应用平台 Goo…