C++排序与比较函数总结

C++各种自定排序总结

1、数组自定义外部排序方法

方法:自己写一个新的比较函数,比较函数的两个参数是数组的类型,这时候会将结构体或基本类型的内置比较函数给覆盖了

struct obj {
    int price;
    ...;
    ...;
};

int num_arr[MAXN];
obj obj_arr[MAXN];
若参数为基本类型:
bool cmp(int a, int b) {
    //这个比较函数的意义是
    //在一个数组中,目前数a是在数b左边的,也就是[..., a, ..., b...]这样的状态
    //如果返回的结果为真,那么就不需要交换他们的位置,否则交换位置
    return a < b;	//如果a
    return b < a;	//如果a>b为真,那么就不交换位置,也就是降序排序
}

若参数为自定义结构体:
bool cmp_num(obj &a, obj&b) {
    //然后按照上面的规则,根据结构体的某种属性进行排序
    return a.price > b.price //例如:这就是按结构体的price属性进行降序排序
}

最后通过algorithm下的sort函数对数组进行排序
sort(num_arr, num_arr + MAXN, cmp_num);
sort(obj, obj + MAXN, cmp_obj);

2、vector自定义外部排序方法

vector排序方法与数组的方法一致,唯一不同的就是sort函数的写法

vector<int> num_vec;
vector<obj> obj_vec;

bool cmp_num();
bool cmp_vec();

sort(num_vec.begin(), num_vec.end());
sort(obj_vec.begin(), obj_vec.end());

若需要直接进行逆序排序,有个比较简单的方法:
sort(num_vec.rbegin(), num_vec.rend());
sort(obj_vec.rbegin(), obj_vec.rend());

3、priority_queue自定义外部排序方法

priority_queue包含在<queue>头文件下

//与数组比较函数定义不同,这里需要定义一个结构体,然后重载()
struct cmp_obj {
    bool operator () (obj &a, obj &b) {
        //通过前面对数组排序的理解,你可能觉得这是个小根堆
        //但是C++的priority_queue默认是大根堆,也就是大的元素在顶上,所以这其实是一个大根堆
        //只要记住priority_queue与数组的sort()是相反的即可
        return a.price < b.price;
    }
}

//这里也要注意,定义堆的排序直接写在泛型内部,第二个泛型指的是用什么容器装这个堆,默认采用vector,直接写就行
priority_queue<obj, vector<obj>, cmp_obj> heap;		//元素为obj的以price进行排序的大根堆

对于基本类型如int, double等若需要选择大根堆或小根堆,可以通过下述实现
priority_queue<int, vector<int>, greater<int>> little_heap;		//定义一个int类型的小根堆
priority_queue<int, vector<int>, less<int>> big_heap;			//定义一个int类型的大根堆,默认就是使用这个

4、结构体自定义排序方法

上面对数组或vector或堆的排序都是通过定义一个外部的比较函数或结构体来排序
实际上可以通过直接在结构体内部重载某个函数实现自定义排序,这样就可以像对基本类型排序一样,对自定义结构体排序

定义结构体
struct obj {
    int price;
    int id;
    
    //注意:这里的obj不能加引用符号,可能是因为内部排序传的是const
    //该重载函数的作用与之前定义的重载函数作用是一致的
    //只需要重载 < 号即可,因为通过一个 < 就能判断出两个对象的大小,> 的作用可以通过 b < a 来实现
    friend bool operator < (obj a, obj b) {
        if(a.id != b.id) return a.id > b.id;
        return a.price < b.price;
    }
    
    //实际上,在3中我们使用的less 就是通过上面这个函数的重载实现的,C++默认是使用less<>,
    //因此这时候我们可以直接写priority,这就相当于priority_queue, less>
    //若对 > 号进行重载,我们就能使用greater来得到一个小根堆了,但其实重载一个 < 更方便,且与之前的排序一致,
    //因此我们只需要重载 < 即可,然后对里面的比较逻辑进行修改,就能达到目的
}

有了上述这个结构体,就能直接像基本类型一样对obj进行排序了
vector<obj> obj_vec;
obj obj_arr[MAXN];
priority_queue<obj> heap;	//id不一致的,则小id在堆顶,否则大price在堆顶



sort(obj_arr, obj_arr + MAXN);
sort(obj.begin(), obj.end());

参考文献:算法笔记

你可能感兴趣的:(算法学习,c++,排序)