关于C++中排序和建堆的比较规则:std::greater()、std::less()、自定义比较规则

这篇具有很好参考价值的文章主要介绍了关于C++中排序和建堆的比较规则:std::greater()、std::less()、自定义比较规则。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

排序和建堆的使用方式(自定义为例)

在C++中,排序和建堆的比较规则是通过比较函数或者比较对象来定义的。这通常涉及到使用函数对象(Functor)或者函数指针,以决定元素之间的大小关系。
举例: 利用函数排序

#include <iostream>
#include <vector>
#include <algorithm>

// 自定义比较函数
bool myComparator(int a, int b) {
    return a > b; // 降序排序
}

int main() {
    std::vector<int> vec = {5, 2, 8, 1, 6};

    // 使用自定义比较函数进行降序排序
    std::sort(vec.begin(), vec.end(), myComparator);

    // 输出排序后的结果
    for (int num : vec) {
        std::cout << num << " ";
    }

    return 0;
}

举例: 利用对象排序,注意sort第三个实参中有括号,是建立临时对象

#include <iostream>
#include <vector>
#include <algorithm>

// 自定义比较对象
struct MyComparator {
    bool operator()(int a, int b) {
        return a > b; // 降序排序
    }
};

int main() {
    std::vector<int> vec = {5, 2, 8, 1, 6};

    // 使用自定义比较对象进行降序排序
    std::sort(vec.begin(), vec.end(), MyComparator());

    // 输出排序后的结果
    for (int num : vec) {
        std::cout << num << " ";
    }

    return 0;
}

举例: 利用对象建堆,注意优先级队列(本例中为小顶堆)第三个模板参数不带括号

#include <iostream>
#include <queue>

// 自定义比较对象
struct MyComparator {
    bool operator()(int a, int b) {
        return a > b; // 小顶堆,小的元素排在前面
    }
};

int main() {
    std::priority_queue<int, std::vector<int>, MyComparator> minHeap;

    // 插入元素
    minHeap.push(5);
    minHeap.push(2);
    minHeap.push(8);
    minHeap.push(1);
    minHeap.push(6);

    // 弹出并输出元素
    while (!minHeap.empty()) {
        std::cout << minHeap.top() << " ";
        minHeap.pop();
    }

    return 0;
}

结论

如果是排序,less<T>是升序,(从左到右遍历下标,数组元素从小到大);greater<T>是降序(从左到右遍历下标,元素从大到小)。
如果是建堆,less<T>是大顶堆,greater<T>是小顶堆。

less()、greater()原理

假设比较规则就是comp(a, b),对于排序来说,左边元素就是前一个a,右边元素就是后一个b;对于建堆,新插入一个元素时,插入到最后一个叶子,这时要整理堆内元素满足大/小顶堆,a代表新插入的结点,b代表它的父节点。
我们写自定义比较规则就可以依照这个规则。
而标准库中的less<T>就是让a比b小,对应排序就是左边比右边小,就是升序;对于建堆就是让新插入节点比它的父结点小,就是大顶堆。
greater<T>相反。

默认都是用less<T>。

自定义规则

这部分参考里的例子写的很好,直接贴过来了。

符合两个条件:
bool:返回值bool
return x<y;:重载<之类的操作符,并且要决定比较什么元素。
PS:建议还要常引用,保险,禁止发生修改要比较的元素可能。

举例:数组
函数:使用时不加括号,加了报错

类的对象:注意,排序时的类必须使用类的对象才对,直接使用类报错。

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

// 重写排序函数
bool cmpfunc(const int &a, const int &b)
{
    return a < b;
    // < 升序; > 降序
}

// 模仿less、greater构建类
struct cmpClass
{
    bool operator()(const int &i, const int &j)
    {
        return (i < j);
    }
}cmpClassObject;		// 注意,排序时的类必须使用类的对象才对,使用类报错。

int main()
{
	// 使用函数
    vector<int> v1 = {2, 3, 1, 6, 2, 5, 4};
    // 使用时不加括号,加了报错
    sort(v1.begin(), v1.end(), cmpfunc);
    for (int i = 0; i < v1.size(); i++)
    {
        cout << v1[i] << " ";
    }
    cout << endl;
    // 1 2 2 3 4 5 6
    
    // 使用类的对象
    vector<int> v2 = {2, 3, 1, 6, 2, 5, 4};
    sort(v2.begin(), v2.end(), cmpClassObject);
    for (int i = 0; i < v2.size(); i++)
    {
        cout << v2[i] << " ";
    }
    cout << endl;
    // 1 2 2 3 4 5 6
    return 0;
}

举例:优先级队列
定义类时同时定义操作符重载函数:操作符重载函数,必须是具体的操作符<之类的,写()报错

自定义类,自定义比较函数:操作符重载函数,必须是具体的操作符<之类的,写()报错

自定义类,自定义包含比较函数的结构体:操作符重载函数,必须是写()

#include <iostream>
#include <queue>
using namespace std;

/******** 定义类时同时定义操作符重载函数 ********/
struct Node1
{
    // 要比较的元素
    int x;
    // 构造函数
    Node1(int x) { this->x = x; }
    // 操作符重载函数,必须是具体的操作符<之类的,写()报错
    bool operator<(const Node1 &b) const
    {
        // 实现less中需要的<,大顶堆
        return x < b.x;
    }
};

/******** 自定义类,自定义比较函数 ********/
struct Node2
{
    // 要比较的元素
    int x;
    // 构造函数
    Node2(int x) { this->x = x; }
};

// 操作符重载函数,必须是具体的操作符<之类的,写()报错
bool operator<(const Node2 &a, const Node2 &b)
{
    // less,大顶堆
    return a.x < b.x;
}

/******** 自定义类,自定义包含比较函数的结构体 ********/
struct Node3
{
    // 要比较的元素
    int x;
    // 构造函数
    Node3(int x) { this->x = x; }
};

struct cmpClass
{
    // 操作符重载函数,必须是写()
    bool operator()(const Node3 &a, const Node3 &b)
    {
        // less,大顶堆
        return a.x < b.x;
    }
};

int main()
{
    /******** 初始化优先级队列的对象p ********/
    // Node1类型,默认使用vector,小顶堆,同 priority_queue<Node1, vector<Node1>, less<Node1> > p;
    priority_queue<Node1> p;

    // 乱序入队
    p.emplace(1);
    p.emplace(3);
    p.emplace(2);

    // 弹出队首
    while (!p.empty())
    {
        cout << p.top().x << " ";
        p.pop();
    }
    cout << endl;
    // 3 2 1

    /******** 初始化优先级队列的对象q ********/
    // 同 priority_queue<Node2> q;
    priority_queue<Node2, vector<Node2>, less<Node2>> q;

    // 乱序入队
    q.emplace(1);
    q.emplace(3);
    q.emplace(2);

    // 弹出队首
    while (!q.empty())
    {
        cout << q.top().x << " ";
        q.pop();
    }
    cout << endl;
    // 3 2 1

    /******** 初始化优先级队列的对象r ********/
    priority_queue<Node3, vector<Node3>, cmpClass> r;

    // 乱序入队
    r.emplace(1);
    r.emplace(3);
    r.emplace(2);

    // 弹出队首
    while (!r.empty())
    {
        cout << r.top().x << " ";
        r.pop();
    }
    cout << endl;
    // 3 2 1
    return 0;
}

参考:
C++:std::greater()、std::less()、自定义比较函数的规则
C++ std::优先级队列priority_queue文章来源地址https://www.toymoban.com/news/detail-809680.html

到了这里,关于关于C++中排序和建堆的比较规则:std::greater()、std::less()、自定义比较规则的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • (Java)数据结构——排序(第一节)堆排序+PTA L2-012 关于堆的判断

    本博客是博主用于复习数据结构以及算法的博客,如果疏忽出现错误,还望各位指正。 堆排序是一种基于堆数据结构的排序算法,其核心思想是将待排序的序列构建成一个最大堆(或最小堆),然后将堆顶元素与最后一个元素交换,再将剩余元素重新调整为最大堆(或最小堆

    2024年04月12日
    浏览(40)
  • 【数据结构】深度剖析最优建堆及堆的经典应用 - 堆排列与topk问题

    🚩 纸上得来终觉浅, 绝知此事要躬行。 🌟主页:June-Frost 🚀专栏:数据结构 🔥该文章分别探讨了向上建堆和向下建堆的复杂度和一些堆的经典应用 - 堆排列与topk问题。 ❗️该文章内的思想需要用到实现堆结构的一些思想(如向上调整和向下调整等),可以在另一篇文章

    2024年02月08日
    浏览(46)
  • C++面试八股文:std::array如何实现编译器排序?

    某日二师兄参加XXX科技公司的C++工程师开发岗位第25面: 面试官: array 熟悉吗? 二师兄:你说的是原生数组还是 std::array ? 面试官:你觉得两者有什么区别? 二师兄:区别不是很大,原生数组(非动态数组)和std::array都在栈上开辟空间,初始化的时候需要提供数组长度,且

    2024年02月10日
    浏览(48)
  • 堆(两种建堆方法)、堆排序和Top-K问题

    是一种完全二叉树,分为大堆,小堆 如果有一个关键码的集合 int K[ ] = {27,15,19,18,28,34,65,49,25,37} ; 把它的所有元素按完全二叉树的顺序存储方式存储 在一个一维数组中,并满足:K i =K 2*i+1 且K i =K 2*i+2 ( K i =K 2*i+1 且K i =K 2*i+2 ) i = 0,1, 2…,则称为小堆(或大堆)。将根节点最大

    2023年04月09日
    浏览(32)
  • <C++> list容器本质|常用接口|自定义排序规则

    ✅作者简介:热爱后端语言的大学生,CSDN内容合伙人 ✨精品专栏:C++面向对象 🔥系列专栏:C++泛型编程 🔥前言 今天把 list 容器的基本操作、常用接口做一个系统的整理,结合具体案例熟悉自定义内部排序方法的使用。 list 与 vector 是STL中最常用的两个容器,如果对vector

    2024年02月01日
    浏览(45)
  • std::copy与memcpy比较

    std::copy和memcpy都可以用于内存块之间的复制操作,但有几个重要的异同点: 相同点: 它们都是C++中的函数,用于内存块之间的复制。 它们都是通过指针操作进行内存复制。 不同点: std::copy是C++标准库中的函数,用于将一个范围内的元素从源地址复制到目标地址。因此它更

    2024年02月12日
    浏览(28)
  • 【数据结构】堆:堆的构建,堆的向上调整算法,堆的向下调整算法、堆排序

    目录 一、堆的定义 1、堆的定义: 2、根节点与其左、右孩子间的联系   二、堆的创建 1、堆的向下调整算法  2、堆的向上调整算法  三、堆排序 1、堆的定义: 堆可以被看作是 一棵 完全二叉树 的 数组 对象 。即在 存储结构上是数组,在逻辑结构上是一棵完全二叉树 。在

    2024年01月22日
    浏览(43)
  • mysql 字符集、比较规则, 比较规则底层逻辑

    字符集的级别 show variables like ‘%charecter%’; character_set_server 服务器级别 一般在 5.7: C:ProgramDataMySQLMySQL Server 5.7my.ini 8.0: C:ProgramDataMySQLMySQL Server 5.7my.ini Linux 系列 vim /etc/my.cnf character_set_server=xxx # 设定默认字符集 collation_server=xxx_chinese_ci # 对应的默认的比较规则 charac

    2024年02月11日
    浏览(48)
  • 关于堆的一切

    首先给出堆的定义: 堆是一颗树,满足堆的性质,即: 对于一个节点,它的权值大于(或小于)它的各个儿子的权值 有这个性质,显然 堆的根节点权值是整个堆中最大或最小的 由此可分为 小根堆 和 大根堆 最常见的堆就是二叉堆 二叉堆是一颗满足 堆的性质 的 完全二叉树

    2024年03月13日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包