目录

C++ sort函数自定义类型排序

目录

整理一下自定义类型排序的相关内容,网上可以查找到的实现方法有三种,内部逻辑相同只是写法不同:

  1. 自定义比较函数
  2. 重载比较运算符(重载小于号)
  3. 定义函数对象并传入

下面是我实现的一个简单案例,需要注意的是,网上有的博客提到所有的实现方式传入的参数都要求是常量引用,不然的话会报错,然而我在实现的时候并没有出现这种问题。但仔细考虑确实这么做比较稳妥,因为在比较时理论上不能对数据进行修改,因而需要常量参数。而传入引用避免了额外内存的开辟以及数据的复制,能够提高效率。

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

using namespace std;
class Person
{
private:
public:
    string name;
    int val;
    int index;
    Person(string n, int v, int i) {
        name = n;
        val = v;
        index = i;
    }
    ~Person() {}

    // 运算符重载
    bool operator<(const Person& p){
        if(val == p.val){
            return name < p.name;
        }
        else{
            return val < p.val;
        }
    }
};

// 函数对象
class myCmp{
    public:
    bool operator()(const Person& a, const Person& b){
        if(a.val == b.val){
            return a.name < b.name;
        }
        else{
            return a.val < b.val;
        }
    }
};

// 自定义比较函数
bool cmp(Person a, Person b){
    if(a.val == b.val){
        return a.name < b.name;
    }
    else{
        return a.val < b.val;
    }
}

int main(){
    vector<string> names = {
        "DaMing",
        "Amy",
        "Amy",
        "DaMing",
        "DaMing",
        "DaLong",
        "DaMing",
        "DaLong",
        "DaMing"
    };
    vector<int> vals = {13, 12, 12, 13, 13, 11, 13, 10, 13};

    // 创建对象数组
    vector<Person> people;
    for(int i = 0; i < names.size(); i++){
        people.push_back(Person(names[i], vals[i], i));
    }

    cout << "自定义比较函数:" << endl;
    sort(people.begin(), people.end(), cmp);
    for(int i = 0; i < people.size(); i++){
        cout << people[i].index << ' ' << people[i].name << ' ' << people[i].val << endl;
    }
    cout << endl;

    cout << "类内重载比较符:" << endl;
    sort(people.begin(), people.end());
    for(int i = 0; i < people.size(); i++){
        cout << people[i].index << ' ' << people[i].name << ' ' << people[i].val << endl;
    }
    cout << endl;

    cout << "函数对象:" << endl;
    sort(people.begin(), people.end(), myCmp());
    for(int i = 0; i < people.size(); i++){
        cout << people[i].index << ' ' << people[i].name << ' ' << people[i].val << endl;
    }
    return 0;
}

程序输出如下:

自定义比较函数:
7 DaLong 10
5 DaLong 11
1 Amy 12
2 Amy 12
0 DaMing 13
3 DaMing 13
4 DaMing 13
6 DaMing 13
8 DaMing 13

类内重载比较符:
7 DaLong 10
5 DaLong 11
1 Amy 12
2 Amy 12
0 DaMing 13
3 DaMing 13
4 DaMing 13
6 DaMing 13
8 DaMing 13

函数对象:
7 DaLong 10
5 DaLong 11
1 Amy 12
2 Amy 12
0 DaMing 13
3 DaMing 13
4 DaMing 13
6 DaMing 13
8 DaMing 13

在写这段代码时,因为sort是不稳定排序,所以我设置了很多具有相同name和val的对象,想要看在排序之后原有前后顺序是否会被打断,但我本地执行这段代码后,并没有发现乱序的现象,可能是数据量不够。如果想要进行稳定的排序,可以调用stable_sort函数。

另外,在自定义函数时,假设传入参数为a和b,如果返回值是a<b,排序之后的效果是升序,反之是降序。