C++ 多条件比较的几种实现方式

文章目录

  • 1 sort()使用自定义比较器
    • 1.1 在类内部定义比较器 -- 声明为静态成员函数
    • 1.2 在函数内部定义比较器 -- lamda表达式
    • 1.3 全局函数比较器
  • 2 重载运算符<
    • 2.1 在结构体中重载运算符<
    • 2.2 在类中重载运算符<
  • 3 重写仿函数bool operator()
  • 4 使用pair排序
  • 5 priority_queue自定义排序规则
  • 6 关于priority_queue中存储pair类型的思考

1 sort()使用自定义比较器

sort使用方法
头文件 #include
sort函数有三个参数:
sort(first,last,cmp);
其中,first是元素的起始地址,last是结束地址,cmp是排序的方式。对[first,last)(一定要注意这里的区间是左闭又开)区间内数据根据cmp的方式进行排序。也可以不写第三个参数,此时按默认排序,从小到大进行排序。

sort() 中的比较函数 compare 要声明为静态成员函数或全局函数,不能作为普通成员函数,否则会报错。

cmpChar实现功能:大写字母大于小写字母,小写字母按 a-z 升序,大写字母按 A-Z 升序

1.1 在类内部定义比较器 – 声明为静态成员函数

class Solution {
public:void CharacterSort(const vector<char> e_char){cout << "before:" << endl;for (auto i : e_char) {cout << i;}cout << endl;std::sort(e_char.begin(), e_char.end(), cmpChar);cout << "after:" << endl;for (auto i : e_char) {cout << i;}cout << endl;}private:static bool cmpChar(const char &a, const char &b){if (a <= 'Z' && b >= 'a')return false;else if (b <= 'Z' && a >= 'a')return true;elsereturn a < b;}};

输入:
vector e_char = {‘C’,‘B’,‘A’,‘c’,‘b’,‘a’};
输出:
before:
CBAcba
after:
abcABC

1.2 在函数内部定义比较器 – lamda表达式

class Solution {
public:void CharacterSort(const vector<char> e_char){cout << "before:" << endl;for (auto i : e_char) {cout << i;}cout << endl;auto cmpChar = [](const char &a, const char &b) {if (a <= 'Z' && b >= 'a')return false;else if (b <= 'Z' && a >= 'a')return true;elsereturn a < b;};std::sort(e_char.begin(), e_char.end(), cmpChar);cout << "after:" << endl;for (auto i : e_char) {cout << i;}cout << endl;}

1.3 全局函数比较器

using namespace std;bool cmpChar(const char &a, const char &b){if (a <= 'Z' && b >= 'a')return false;else if (b <= 'Z' && a >= 'a')return true;elsereturn a < b;}class Solution {
public:void CharacterSort(const vector<char> e_char){cout << "before:" << endl;for (auto i : e_char) {cout << i;}cout << endl;std::sort(e_char.begin(), e_char.end(), cmpChar);cout << "after:" << endl;for (auto i : e_char) {cout << i;}cout << endl;}

2 重载运算符<

例子:按年月日升序排序。

2.1 在结构体中重载运算符<

#include <algorithm>
#include <iostream>
#include <vector>using namespace std;struct date {int year;int month;int day;//在结构体中重载运算符<bool operator<(const date &a) const{// 重载<符号来比较日期的大小if (year == a.year) {if (month == a.month) {return day < a.day;} else {return month < a.month;}} else {return year < a.year;}}
};
// 在结构体外部重载运算符<
/*
bool operator<(const date &a, const date &b)
{// 重载<符号来比较日期的大小if (a.year == b.year) {if (a.month == b.month) {return a.day < b.day;} else {return a.month < b.month;}} else {return a.year < b.year;}
}
*/int main()
{cout << "Hello Word!\n";vector<date> exam;exam.push_back({1997, 8, 19});exam.push_back({1990, 1, 1});exam.push_back({1997, 9, 30});exam.push_back({1990, 1, 20});cout << "before:";for (auto e : exam) {cout << "[" << e.year << "," << e.month << "," << e.day << "]; ";}sort(exam.begin(), exam.end());cout << "\nafter:";for (auto e : exam) {cout << "[" << e.year << "," << e.month << "," << e.day << "]; ";}return 0;};

输出:

这里一定要注意一下:

参数类型如果是自定义类型,比如自己定义的结构体,类,尽管sort函数默认是从小到大排列,但是这里必须要重载比较运算符“<”!!!

2.2 在类中重载运算符<

#include <algorithm>
#include <iostream>
#include <vector>using namespace std;class date {
public:int year;int month;int day;// 在类内部重载运算符<bool operator<(const date &a){// 重载<符号来比较日期的大小if (year == a.year) {if (month == a.month) {return day < a.day;} else {return month < a.month;}} else {return year < a.year;}}
};
// 在类外部重载运算符<
/*
bool operator<(const date &a, const date &b)
{// 重载<符号来比较日期的大小if (b.year == a.year) {if (b.month == a.month) {return a.day < b.day;} else {return a.month < b.month;}} else {return a.year < b.year;}
}
*/
int main()
{cout << "Hello Word!\n";vector<date> exam;exam.push_back({1997, 8, 19});exam.push_back({1990, 1, 1});exam.push_back({1997, 9, 30});exam.push_back({1990, 1, 20});cout << "before:";for (auto e : exam) {cout << "[" << e.year << "," << e.month << "," << e.day << "]; ";}sort(exam.begin(), exam.end());cout << "\nafter: ";for (auto e : exam) {cout << "[" << e.year << "," << e.month << "," << e.day << "]; ";}return 0;
};

在这里插入图片描述

3 重写仿函数bool operator()

sort函数的默认比较函数std:less和std::greater,内部实现就是重载了运算符()。
在这里插入图片描述

int test[10] = {4, 1, 3, 7, 5, 8, 2, 9, 6, 10};
// 注意这里创建了greater对象,sort函数调用greater对象的()运算符重载方法
sort(test, test + 10, greater<int>());

这里首先调用的是greater类默认构造方法,返回一个对象并传递给sort函数sort函数内部调用对象(a,b)时调用的是对象的运算符()重载方法来进行比较。

这里重载了()运算符其实是构造了一个“伪函数”,也就是可以把类的对象作为函数来使用。

模仿greater和less模板类的定义,我们也可以自己定义比较器类:

#include <algorithm>
#include <iostream>
#include <vector>using namespace std;class date {
public:int year;int month;int day;
};struct MyLess  // 自定义比较器类
{bool operator()(const date &a, const date &b) const{if (a.year == b.year) {if (a.month == b.month) {return a.day < b.day;} else {return a.month < b.month;}} else {return a.year < b.year;}}
};int main()
{cout << "Hello Word!\n";vector<date> exam;exam.push_back({1997, 8, 19});exam.push_back({1990, 1, 1});exam.push_back({1997, 9, 30});exam.push_back({1990, 1, 20});cout << "before:";for (auto e : exam) {cout << "[" << e.year << "," << e.month << "," << e.day << "]; ";}sort(exam.begin(), exam.end(), MyLess());cout << "\nafter: ";for (auto e : exam) {cout << "[" << e.year << "," << e.month << "," << e.day << "]; ";}return 0;
};

在这里插入图片描述

4 使用pair排序

头文件:

#include <utility>  #pair头文件

定义:

pair<string,int> p; 
//① 将类型定义写在前面,后面用小括号内两个元素的方式。
pair<string,int>("haha",5)
//② 使用自带的 make_pair 函数。
make_pair("haha",5)

pair<typeName1,typeName2> name,可以是任意基本数据类型或容器。

pari的排序规则默认先比较第一个元素,第一个相等比较第二个。

#include <algorithm>
#include <iostream>
#include <vector>
#include <utility>using namespace std;int main()
{cout << "Hello Word!\n";std::vector<std::pair<int, std::pair<int, int>>> vec;vec.push_back(std::make_pair(1997, std::make_pair(8, 19)));vec.push_back(std::make_pair(1990, std::make_pair(1, 11)));vec.push_back(std::make_pair(1997, std::make_pair(9, 30)));vec.push_back(std::make_pair(1990, std::make_pair(1, 30)));cout << "\nbefore: ";for (auto e : vec) {std::cout << e.first << "," << e.second.first << "," << e.second.second << "; ";}cout << "\nless:   ";std::sort(vec.begin(), vec.end());for (auto e : vec) {std::cout << e.first << "," << e.second.first << "," << e.second.second << "; ";}cout << "\ngreater:";std::sort(vec.begin(), vec.end(), greater<std::pair<int, std::pair<int, int>>>());for (auto e : vec) {std::cout << e.first << "," << e.second.first << "," << e.second.second << "; ";}cout << std::endl;return 0;
};

在这里插入图片描述

5 priority_queue自定义排序规则

  1. 头文件
#include <queue>
  1. 定义
priority_queue<int> a;  //对于基础类型 默认是大顶堆
priority_queue<int, vector<int>, less<int> > a;  // 等同于priority_queue<int> a 
priority_queue<int, vector<int>, greater<int> > c;  //这样就是小顶堆

priority_queue<Type, Container, Functional>
Type为数据类型; Container为保存数据的容器(Container必须是用数组实现的容器,比如vector,deque等等,但不能用 list,STL里面默认用的是vector);Functional为元素比较方式。
如果不写后两个参数,那么容器默认用的是vector,比较方式默认用operator<,也就是优先队列是大顶堆,队头元素最大。
当需要用自定义的数据类型时才需要传入这三个参数;

优先队列具有队列的所有特性,包括基本操作,只是在这基础上添加了内部的一个排序,它本质是一个堆实现的。

3 自定义排序规则
priority_queue使用自定义的数据类型,同时也要实现自定义排序规则,有2种方式:

  1. 重载运算符<
  2. 重写仿函数
    priority_queue自定义排序规则,返回true要交换位置,这与前面提到的几种排序返回true不一样,容易记错。
#include <algorithm>
#include <iostream>
#include <vector>
#include <queue>using namespace std;struct date {int year;int month;int day;// 重载运算符<bool operator<(const date &a) const{// 重载<符号来比较日期的大小,返回true交换位置if (year == a.year) {if (month == a.month) {return day < a.day;} else {return month < a.month;}} else {return year < a.year;}}
};struct myCompare  // 重写仿函数,返回true交换位置
{bool operator()(const date &a, const date &b) const{if (a.year == b.year) {if (a.month == b.month) {return a.day < b.day;} else {return a.month < b.month;}} else {return a.year < b.year;}}
};int main()
{cout << "Hello Word!\n";priority_queue<date> vec_1;vec_1.push({1997, 2, 22});vec_1.push({1990, 10, 9});vec_1.push({1997, 2, 5});vec_1.push({1990, 8, 9});priority_queue<date, vector<date>, myCompare> vec_2;vec_2.push({2007, 2, 22});vec_2.push({2000, 10, 9});vec_2.push({2007, 2, 5});vec_2.push({2000, 8, 9});cout << "\noperator< : ";while (!vec_1.empty()) {std::cout << vec_1.top().year << ","<<vec_1.top().month<< ","<<vec_1.top().day<< ";";vec_1.pop();}cout << "\noperator(): ";while (!vec_2.empty()) {std::cout << vec_2.top().year << ","<<vec_2.top().month<< ","<<vec_2.top().day<< ";";vec_2.pop();}cout << std::endl;return 0;
};

在这里插入图片描述

6 关于priority_queue中存储pair类型的思考

当priority_queue不指定排序方式是默认是大根堆(降序),pair默认std::less(升序),但如果priority_queue存储的是pair类型的时候呢?
先说结论:priority_queue<pair<int, int>> myqueue,排序结果为降序.

int main()
{cout << "Hello Word!\n";priority_queue<pair<int, int>> myqueue;//若插入数据类型的构造函数接受多个参数,push只接受该类型的实例,emplace不仅能接受该类型的实例,还能接受该类型构造函数的参数。myqueue.push({1990, 7});myqueue.emplace(1997, 7);myqueue.emplace(2000, 8);myqueue.emplace(2000, 9);myqueue.emplace(1000, 7);while (!myqueue.empty()) {cout << myqueue.top().first << " " << myqueue.top().second << endl;myqueue.pop();}
return 0;
};

在这里插入图片描述

有的文章提到优先队列priority_queue中使用pair,个人觉得使用一种就行,priority_queue结合pair有什么优势欢迎评论区留言。

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

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

相关文章

IPO:动力电池行业变天,不生产电芯的幂源科技为何也要卷?

幂源科技的真正角色&#xff0c;是月老&#xff1f; 最近&#xff0c;动力电池正处于市场重构阶段。一边是供给端动力电池产能过剩&#xff0c;一边是需求端新能源车企加码电池自研。供需不匹配孕育出了新机遇&#xff0c;产业链的连接者与赋能者成为市场所需。而幂源科技控股…

学生用台灯哪个品牌比较好?口碑最好的护眼台灯推荐

台灯是现在很多朋友都在使用的照明灯具&#xff0c;对于晚上工作学习、看书休闲都有很大的裨益&#xff0c;但是选择台灯也注重护眼效果&#xff0c;在此基础上才是讨论性价比的问题&#xff0c;如果光线让人眼不舒适&#xff0c;那么多便宜的台灯都不划算。 ● 怎样的护眼台灯…

基于FPGA的万兆以太网学习(1)

万兆(10G) 以太网测速视频:FPGA 实现UDP万兆以太网的速度测试 1 代码结构 2 硬件需求 SFP+屏蔽笼可以插入千兆或万兆光模块。SFP+信号定义与 SFP 一致。 3 Xilinx IP 10 Gigabit Ethernet Subsystem IP说明 文章链接: Xilinx IP 10 Gigabit Ethernet Subsystem IP 4 E…

Vue3响应式系统(二)

Vue3响应式系统(一)https://blog.csdn.net/qq_55806761/article/details/135587077 六、嵌套的effect与effect栈。 什么场景会用到effect嵌套呢&#xff1f;听我娓娓道来。 就用Vue.js来说吧&#xff0c;Vue.js的渲染函数就是在effect中执行的&#xff1a; /*Foo组件*/ const…

循环神经网络的变体模型-LSTM、GRU

一.LSTM&#xff08;长短时记忆网络&#xff09; 1.1基本介绍 长短时记忆网络&#xff08;Long Short-Term Memory&#xff0c;LSTM&#xff09;是一种深度学习模型&#xff0c;属于循环神经网络&#xff08;Recurrent Neural Network&#xff0c;RNN&#xff09;的一种变体。…

Android NDK Crash信息收集捕获和日志异常定位分析(addr2line)

Android NDK 闪退日志收集与分析 我们在开发过程中,Android JNI层Crash问题或者我们引用的第三方.so库文件报错,都是一个比较头疼的问题。相对Java层来说,由于c/c++造成的crash没有输出如同Java的Exception Strace堆栈信息,所以定位问题也是个比较艰难的事情。 Google Br…

HCIA的路由协议

动态路由协议/静态路由协议 静态路由协议和动态路由协议的区别&#xff1a; 静态路由协议的缺点&#xff1a; 配置繁琐 针对拓扑的变化不能够自动收敛 只适用于小型网络 静态路由协议优点&#xff1a; 占用资源少 安全 稳定 动态路由协议的优点&#xff1a; 配置简单 针对拓…

前端项目配置 Dockerfile 打包后镜像部署无法访问

Dockerfile 配置如下&#xff1a; FROM node:lts-alpineWORKDIR /app COPY . . RUN npm install RUN npm run buildEXPOSE 3001CMD ["npm", "run", "preview"]构建镜像 docker build -t vite-clarity-project .启动镜像容器 docker run -p 30…

进程(一) 进程概念

文章目录 什么是进程呢&#xff1f; 描述进程-PCBtask_struct-PCB的一种task_struct内容分类 查看进程通过系统目录查看通过ps命令查看通过系统调用获取进程的PID和PPID通过系统调用创建进程- fork&#xff08;&#xff09;函数 fork()函数fork函数做了什么&#xff1f;fork之后…

Vue加载序列帧动图

解读方法 使用<img :src"currentFrame" alt"加载中" /> 加载图片动态更改src的值使用 requestAnimationFrame 定时更新在需要的页面调用封装的组件 <LoadToast v-if"showLoading" /> 封装组件 <template><div class"…

CTF CRYPTO 密码学-1

题目名称&#xff1a;enc 题目描述&#xff1a; 压缩包中含两个文件&#xff1a;一个秘钥d.dec&#xff0c;一个密文flag.enc 解题过程&#xff1a; Step1&#xff1a;这题是一个解密他题目&#xff0c;尝试openssl去ras解密 工具简介 在Kali Linux系统中&#xff0c;openss…

React16源码: React中的异步调度scheduler模块的源码实现

React Scheduler 1 ) 概述 react当中的异步调度&#xff0c;称为 React Scheduler发布成单独的一个 npm 包就叫做 scheduler这个包它做了什么&#xff1f; A. 首先它维护时间片B. 然后模拟 requestIdleCallback 这个API 因为现在浏览器的支持不是特别的多所以在浏览当中只是去…

【计算机图形学】习题课:Viewing

【计算机图形学】Viewing 部分问题与解答 CS100433 Computer Graphics Assignment 21 Proof the composed transformations defined in global coordinate frame is equivalent to the composed transformations defined in local coordinate frame but in different composing…

1月14-17日为技术测试期!字节与腾讯上演“大和解”,抖音全面开放《王者荣耀》直播

综合整理&#xff5c;TesterHome社区 来源&#xff5c;《王者荣耀》官方、界面新闻 北京商报、IT之家 1月13日&#xff0c;腾讯游戏《王者荣耀》官方微博发布消息宣布&#xff0c;从1月21日起&#xff0c;《王者荣耀》抖音直播将全面开放。 为了筛查开播期间可能遇到的所有技…

几何_直线方程 Ax + By + C = 0 的系数A,B,C几何含义是?

参考&#xff1a; 直线方程 Ax By C 0 的系数A&#xff0c;B&#xff0c;C有什么几何含义&#xff1f;_设直线 l 的方程为axbyc0 怎么理解-CSDN博客 1. A B的含义&#xff1a;组成一个与直线垂直的向量 我们先来看A和B有什么含义。 在直线上取任意两点 P1:&#xff08;x1…

OceanBase集群部署

我认为学习一个中间件比较好的方式是&#xff0c;先了解它的架构和运行原理&#xff0c;然后动手部署一遍&#xff0c;加深对它的了解&#xff0c;再使用它&#xff0c;最后进行总结和分享 本篇介绍OceanBase部署前提配置和集群部署 1.使用开源免费的社区版&#xff0c;企业版…

[Android] Android架构体系(1)

文章目录 Android 的框架Dalvik 虚拟机JNI原生二进制可执行文件Android NDK中的binutils Bionic谷歌考虑到的版权问题Bionic与传统的C标准库&#xff08;如glibc&#xff09;的一些不同 参考 Android 的框架 Android 取得成功的关键因素之一就是它丰富的框架集。 没有这些框架…

架构08- 理解架构的模式2-管理和监控

大使模式&#xff1a;构建一个辅助服务&#xff0c;代表消费者使用服务或应用程序发送网络请求。 进程外的代理服务&#xff08;之前介绍中间件的时候也提到了&#xff0c;很多框架层面的事情可以以软件框架的形式寄宿在进程内&#xff0c;也可以以独立的代理形式做一个网络中…

AI绘图制作红包封面教程

注意&#xff1a;有不懂的话可加入QQ群聊一起交流&#xff1a;901944946欢迎大家关注微信公众号【程序猿代码之路】&#xff0c;每天都会不定时的发送一些红包封面&#xff01;&#xff01; 2024的春节即将到来&#xff0c;而在这春节到来之前&#xff0c;就有一个非常爆火的小…

黑马程序员 Java设计模式学习笔记(一)

目录 一、设计模式概述 1.1、23种设计模式有哪些&#xff1f; 1.2、软件设计模式的概念 1.3、学习设计模式的必要性 1.4、设计模式分类 二、UML图 2.1、类图概述 2.2、类图的作用 2.3、类图表示法 类的表示方式 类与类之间关系的表示方式 关联关系 聚合关系 组合…