前言:
sort()
函数是<alogrithm>
库下的一个函数,sort()
函数是不稳定的,如果需要稳定的排序算法,可以转为使用stable_sort()
,stable_sort
的实现是基于归并排序的,它的时间复杂度为O(nlogn)
,一般情况下会比基于快排的sort()
稍慢。
1. sort函数调用的两种方式
方法1(默认) | void sort (RandomAccessIterator first, RandomAccessIterator last); |
---|---|
方式2 (自定义) | void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp); |
- 默认: 两个参数first,last,将 [first, last) 区间内元素 升序 排列。【注意区间为左闭右开】
- 自定义排序: 需用户指定排序规则Compare comp,将 [first, last)区间内的元素按照用户指定的顺序排列。
举例:
/*
Description:
jlh很喜欢吃水果,苹果是他最喜欢的,其次是梨。
他天天想着吃水果,竟然感动了女娲大神,
女娲大神给了他n个篮子,让他选择其中的m个(m<=n)个篮子。
每个篮子里有a个苹果和b个梨。请你们帮jlh选择篮子吧。
Input:
输入一个t(t<=10),表示有t组测试数据,
再输入n和m(0=<m<=n<=100000),
接下来的n行,输入a和b表示苹果和梨的数量。
Output:
按jlh选择的顺序
(先选苹果多的,苹果数量相同选梨多的,两者相同选序号小的)
篮子的序号(1-n),m个数用空格隔开。
Sample Input:
2
2 1
2 0
1 4
3 2
3 4
2 6
3 5
Sample Output:
1
3 1
*/
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdio>
using namespace std;
/**
* 自定义篮子
*/
class basket{
public:
int apple; // 苹果数量
int pear; // 梨的数量
int id; // id
};
/**
* 自定义比较函数
* @param a 篮子a
* @param b 篮子b
* @return
* 若a,b中苹果数量不等,返回a, b 篮子中苹果数量;a>b返回true
* 若a,b中梨的数量不等,返回a, b 篮子中梨数量;a>b返回true
* 否则比较id小的篮子;a<b返回true
*/
bool compareFruitAlgorithm(const basket a, const basket b) {
if (a.apple != b.apple)
return a.apple > b.apple; // 若a,b中苹果数量不等,返回a, b 篮子中苹果数量;a>b返回true
else if (a.pear != b.pear)
return a.pear > b.pear; // 若a,b中梨的数量不等,返回a, b 篮子中梨数量;a>b返回true
else return a.id < b.id; // 否则比较id小的篮子;a<b返回true
}
int main() {
// Input: 输入一个t(t<=10),表示有t组测试数据,再输入n和m(0=<m<=n<=100000),接下来的n行,输入a和b表示苹果和梨的数量。
// Output: 按jlh选择的顺序(先选苹果多的,苹果数量相同选梨多的,两者相同选序号小的)篮子的序号(1-n),m个数用空格隔开。
int t;
cin >> t;
while(t--) { // while(0)就是false,便跳出循环。
int n, m; // 共有n个篮子,其中选m个篮子
cin >> n >> m;
vector<basket> baskets(n); // 建立n个篮子
// 装入
for (int i=0; i<n; ++i) {
cin >> baskets[i].apple >> baskets[i].pear; // 装入苹果和梨的数量
baskets[i].id=i+1;
}
// 排序
sort(baskets.begin(), baskets.end(), compareFruitAlgorithm);
// vector.begin()就是指向第一个元素:[0]位置
// vector.end()指向最后一个元素的后一个元素位置。
// 输出
// 这里要注意,题目给的示例中,输出每一排最后一个元素之后是没有空格的,所以要分类讨论
// 1.不是这一排最后一个要输出的元素,输出id之后再带上" ";
// 2.是这一排最后一个元素,仅仅输出这个id,并且换行。
for (int i=0; i<m; ++i) {
if (i != m-1)
printf("%d ", baskets[i].id); // 不是这一排最后一个要输出的元素,输出id之后再带上" "
else printf("%d\n", baskets[i].id); // 是这一排最后一个元素,仅仅输出这个id,并且换行。
}
}
}
2. sort函数使用场景
由于在排序过程中涉及到元素交换等操作,所以sort函数仅支持可随机访问的容器,如数组, string、vector、deque等。
3.sort函数排序原理
sort()
并非只是普通的快速排序,除了对普通的快速排序进行优化,它还结合了插入排序和堆排序。根据不同的数量级别以及不同情况,能自动选用合适的排序方法。当数据量较大时采用快速排序,分段递归。一旦分段后的数据量小于某个阀值,为避免递归调用带来过大的额外负荷,便会改用插入排序。而如果递归层次过深,有出现最坏情况的倾向,还会改用堆排序。
所以无论元素初始时为何种状态,sort()
的平均排序复杂度为均为O(nlog2(n))
,具有不错的的性能,在刷算法题时,可以直接使用sort()来对数据进行排序,而不需手动编写排序函数。
4. 自定义comp函数返回true或false作用
bool cmp(int num1, int num2) { // 实现降序排列
return num1 > num2; // num1大于num2时返回true,否则返回false
}
自定义函数返回值为bool类型
- 若返回true,则表示num1 与num2应该交换顺序;
- 若返回false, 则num1 与num2 保持原有顺序;