一、sort()函数简介
在STL标准函数库中提供了一种sort()排序函数,其底层的实现方式是快速排序。
该函数的原型:
void sort(start, end, cmp)
其中的三个参数分别表示:
1)start是迭代器的起始地址。
2)end是结束地址。
3)cmp是可选参数,用来指定排序的方法,当没有指定时,默认升序。
即排序的区间是 [ start,end ) ,排序的方式是默认升序。
二、如何自定义排序方式
这里我首先给出两种定义cmp的方法以及传入它们之后得到的结果。
//首先第一种
bool cmp1(int a, int b)
{
return a < b;
}
//然后第二种
bool cmp2(int a, int b)
{
return a > b;
}
int a[] = {10, 10, 56, 78, 91, 102, 1, 2};
//首先,不带cmp参数,默认升序
sort(a, a + sizeof(a)/sizeof(int));
//排序后结果:1 2 10 10 56 78 91 102
//然后传入参数cmp1
sort(a, a + sizeof(a)/sizeof(int), cmp1);
//排序后结果仍然是:1 2 10 10 56 78 91 102
//最后传入参数cmp2
sort(a, a + sizeof(a)/sizeof(int), cmp2);
//排序后结果变为:102 91 78 56 10 10 2 1
可能这里大家还是看不出来,到底参数cmp是怎么实现自定义排序方式的?
首先,sort是默认升序的,我们之前说过,它的底层实现方式是快速排序,所以说明sort()在排序的过程中,也是进行两两元素的比较。
所以我们可以这样理解,也就是sort()函数会按照cmp中的方法,在容器中进行两两元素的比较,如果返回值结果为假,那么函数会互换他们的位置,如果返回结果为真,就保持原来的位置不变。
那么,对于参数cmp1,可以这样解释:
如果返回值结果为假,那么函数会互换他们的位置;如果返回结果为真,就保持原来的位置不变。也就是如果a < b成立,那么就保持不变,否则就交换位置,所以我们可以知道容器中都是小的在前,大的在后,即仍然是升序,所以此时和不加cmp参数是一样的结果。
所以,不难想到,如果把cmp1函数中的 return a < b 改成 return a > b; 那么就是从 大 到 小 排序,可以看成cmp函数在这里对比较运算符进行了重构。
sort()函数也可以运用于其他STL容器的排序。(在优先队列中,我们需要使用结构体来自定义cmp方法)
三、实用的sort函数
在这里介绍一种非常实用的方法,也就是使用sort()函数来排序结构体数组。
平常做题的时候可能会遇到下面几种情况:
1)一个结构体需要排序,里面属性太多,只根据一个属性进行排序时,其余属性也需要同步交换,单纯使用简单的排序算法需要交换的属性则太多,开一堆临时变量又比较麻烦。
2)一个结构体需要排序,但是排序依据不唯一。
例如下面的结构体:
#include<iostream>
#include<algorithm>
using namespace std;
typedef struct student{
char name[50]; //学生姓名
int sum; //总成绩
int chinese; //语文成绩
int math; //数学成绩
int english; //英语成绩
}student;
int main()
{
return 0;
}
此时,我们就可以充分利用参数cmp来自定义排序方式:
bool cmp(student x, student y) //参数类型要写成结构体类型,
{
return x.sum > y.sum;
}
cmp函数的形参类型要与待排序的数据类型一致,原因我们自然也很清楚,因为是对数据两两进行比较,所以类型当然要一致的。
本篇只是介绍了sort()函数一些简单的用法,具体更高级的用法,大家可以在实践中慢慢感悟。