数据结构与函数使用2:排序函数sort
本文目的
简单的介绍一下sort函数是什么,如何自定义排序准则使用
前置知识点
- 各种排序算法
- 仿函数写法
- 类与模板
- C++基本语法基础
- 迭代器
- 二元判断式(也叫二元谓词)
排序函数sort简介
顾名思义就是排序
sort函数的算法原理
似乎会根据各种数据情况,选用不同的算法。常见应该有快排,归并排序等,时间平均到o(nlogn),这里主要介绍函数使用,不做算法具体介绍
sort函数的使用
1. 头文件定义
#include<algorithm>
2. 函数使用
函数的使用以vector容器为例子
2.1 相关函数定义
有两个sort函数,一个是三个形参(含比较器),一个是两个形参(默认从小到大排序)
这里只考虑三个参数的
查看头文件<algorithm>里面的sort定义是这样的,使用了模板函数(会自动识别元素内容)
* @param __first An iterator.
* @param __last Another iterator.
* @param __comp A comparison functor.
template<typename _RandomAccessIterator, typename _Compare>
inline void sort(_RandomAccessIterator __first, _RandomAccessIterator __last,_Compare __comp)
模板的定义参数如下
- 参数1:_RandomAccessIterator __first,容器首部迭代器(排序时包含首部迭代器指向的元素)
- 参数2:_RandomAccessIterator __last,容器尾部迭代器(排序时不包含尾部迭代器指向的元素)
- 参数3:_Compare __comp,一个比较器用于定义优先级,是一个比较函数
- 上面三个参数的类型都是模板,可以自动识别
2.2 默认优先方式的函数使用(小到大)
这个时候其实是用了另一个只有两个形参的函数
#include<vector>
using namespace std;
vector<int> nums = {5,2,3,1};
int main(){
sort(nums.begin(),nums.end());
//nums.begin()返回首部迭代器,可以加数字来移动
//nums.end()返回尾部迭代器(最后一个元素的下一个位置),可以加数字来移动
}
2.3 自定义优先级的函数使用
模板的第三个参数是比较器,是一个比较函数,一个二元判断式子
参考《C++标准库 自修教程与参考手册》9.9 排序算法(Sorting Algorithms)
__comp应当是一个二元判断式op(elem1,elem2),作为排序准则进行排序
参考《C++标准库 自修教程与参考手册》5.8.2判断式/谓词(Predicates)
算法有一种特殊的辅助函数,叫做判断式predicates,也有翻译成谓词的(不好听)。
返回bool,通常用来定义排序准则和搜寻准则
二元判断式(Binary Predicates) 的典型用途是比较两个参数的特定属性,
如果需要以自己的原则进行排序的时候往往会用上
一个比较典型的二元判断式声明如下bool cmp(const typename&a, const typename&b); //typename是具体的类型名称
比较函数的比较方式可以多种多样,举个例子这里使得函数从大到小排序。
记忆一下,比较函数的左边的值排在队伍前面
#include<vector>
using namespace std;
vector<int> nums = {5,2,3,1};
//左边的值是大一点的值,所以大一点的值排在前面
bool cmp(const int&a, const int&b){
return a > b;
}
int main(){
sort(nums.begin(),nums.end(),cmp);
}
对于排序算法sort,这里认为左边值是优先值(和priority_queue优先队列不同,右边是优先值,右边的的数总是在堆顶)
- 注意,如果cmp是类成员函数,必须是静态的,因为非静态在编译的时候会添加this指针形参,就不再满足sort函数的模板要求了
2.4 仿函数实体作为比较函数填入形参
ps: 其实由于sort是模板函数,函数指针的函数调用方式是函数指针fun_p(a,b),而仿函数的调用方式也刚好是fun_objcet(a, b),所以这里填写仿函数实体进去也不会报错。
#include<vector>
using namespace std;
vector<int> nums = {5,2,3,1};
//左边的值是大一点的值,所以大一点的值排在前面
class cmp{
public:
bool operator()(const int & a, const int & b){
return a<b;
}
};
int main(){
sort(nums.begin(),nums.end(),cmp());//cmp()是构造函数实例化了一个有operator()()的实体
}
参考文献
《C++标准库 自修教程与参考手册》5.8.2判断式(Predicates)p121
《C++标准库 自修教程与参考手册》9.9 排序算法(Sorting Algorithms) p397