C++ —— sort与比较器

一、基础知识

  c++内置一个排序函数:sort,其头文件为#include<algorithm>,函数原型为:

void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);

  需要三个参数:

  1. 起始位置(迭代器),参与排序的第一个元素的地址
  2. 结束位置(迭代器),参与排序的最后一个元素的后一个元素的地址
  3. 比较器(函数指针),此参数可以省略,省略后自动使用“less<>”结构体按升序排序,而该结构体只依赖于“ operator< ”,即<号 。因此,参与排序的元素必须具有 “ < ”,要么是int,double等自带的<,要么是程序员自己重载的< 

 

 可省略比较器的示例:

  以下仅演示重载 < 的情况,自带 < 过于简单不必赘述。

复制代码
using namespace std;

struct node {
    int x;
    bool operator< (node& a) const{    //为node类型重载的<
        return x < a.x ? true : false;
    }
};


void test01() {
    vector<node>v;
    node a, b, c, d;
    a.x = 3;
    b.x = 4;
    c.x = 1;
    d.x = 2;
    v.push_back(a); v.push_back(b); v.push_back(c); v.push_back(d);

    sort(v.begin(), v.end());  //由于node类型现在具有<,可以省略比较器

    for (int i = 0; i < v.size(); ++i)
        cout << v[i].x << endl;
}


int main() {
    test01();
}
复制代码

结果如下:

 

 

 

 

二、比较器

  如果我们不想给指定类型重载<,但又想使用sort为这种类型排序。或者是我们想按非默认的方式进行排序,例如降序。此时我们就可以带上比较器。比较器本质上是一个函数指针,其对应的函数可以满足排序需求。因此我们要写的是一个函数,也可以是一个结构体伪函数。

自定义函数:

//自定义函数,降序
bool mycmp(const node& a,const node& b) {  
    return a.x > b.x ? true : false;
}

sort改为:

sort(v.begin(), v.end(), mycmp);

mycmp是指向mycmp()函数的指针,直接作为比较器。

 

结构体伪函数:

复制代码
//伪函数,降序
struct mycmp2
{
    bool operator() (const node& a, const node& b) {
        return a.x > b.x ? true : false;
    }
};
复制代码

sort改为:

sort(v.begin(), v.end(), mycmp2());

mycmp2是结构体,mycmp2()作为比较器。

结果如下:

 

 

 

比较器函数的写法:

  1. 一般定义在类或结构体外部(理论上写在内部的也可以通过函数指针取到地址并作为比较器,但暂且没找到正确写法)
  2. 返回类型必须是bool
  3. 传入参数必须为2个。我们只希望sort对元素进行排序,排序过程中不能对值产生影响,所以一般用const修饰传入参数。同时,为加快速度,一般传引用
  4. 如何按需求编写比较器?记住如下规则:当返回true时,排序后第一个传参会排在前面,第二个传参排在后面;返回false时,排序后第二个传参排在前面,第一个排在后面。也可以这样理解:对于一个容器,从前往后取数,每次取相邻两个,传给比较器进行比较,每次结果都是true,则该容器是正确排序的容器。

例如:我们希望按x的降序对node型元素排序,也就是说需求如下:a.x < b.x 时将b排在a前面,而a.x > b.x时,将a排在b前面,对于=的情况没有要求,根据规则编写如下:

bool mycmp(const node& a,const node& b) {  
    return a.x > b.x ? true : false;
}

a.x > b.x时返回true,则排序后第一个传参a排在前面,第二个传参b排在后面;

a.x<=b.x时返回false,则排序后第二个传参b排在前面,第一个传参a排在后面,满足需求

 

避坑:

  优先队列priority_queue底层是堆,比较器比较的对象是从叶子到根的元素,因此最后自动排序出来的顺序是反直觉的。例如

priority_queue <int,vector<int>,less<int> >q;

该优先队列是大根堆,按降序排列

 

posted @   汇编不会编  阅读(667)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示