sort排序函数
中等14一键排序:C++ 的 sort 函数,像魔法一样整理你的数据
你是不是经常为考试成绩排名、零花钱花费记录或者一堆乱糟糟的数字发愁?要是有一个魔法,只要说“从低到高排好”,所有数字就自动站好队,那该多省事!
C++ 的 sort 函数就是这样的魔法——它能在瞬间把数组、vector 等容器里的数据排好顺序。不管你是想从小到大(升序)还是从大到小(降序),它都能轻松搞定。
要使用 sort,必须先请它出场:在代码开头加上 #include <algorithm>。这就像书架上放了一个“整理工具箱”,sort 就在里面。
基本用法:告诉它“从哪里排到哪”
sort 函数的调用方法是:
sort(起始地址, 结束地址);
这里有个特别重要的规律:结束地址是“最后一个元素的下一个位置”,也就是不包含这个位置。
举个例子,如果你的书架有 10 本书,编号 09,你想整理前 5 本(编号 04),那么起始地址是第 0 本(书架的起点),结束地址是编号 5 的那本书的位置(虽然那里并没有书)。
在 C++ 数组里,这个地址通常写作 arr + n,其中 n 是要排序的元素个数。
对于 vector 容器,不需要自己算地址,直接用 v.begin() 表示起点,v.end() 表示终点(最后一个元素的下一个位置)。
下面的例子会让你更清楚。
例1:给零花钱排个序(从小到大)
假设你记录了一周每天的零花钱支出:5 元、2 元、8 元、1 元、9 元。用 sort 可以按金额从小到大排序。
#include <iostream>
#include <algorithm> // sort 的家
using namespace std;
int main() {
int arr[] = {5, 2, 8, 1, 9};
int n = 5;
// 对整个数组排序,arr 是起始地址,arr+n 是不包含的结束地址
sort(arr, arr + n);
cout << "排序后的零花钱:";
for (int i = 0; i < n; i++) {
cout << arr[i] << " ";
}
cout << endl; // 输出:1 2 5 8 9
return 0;
}
小提示:这里的 arr + n 指向数组最后一个元素的下一个位置,也就是不存在的第 5 个元素。如果写成 arr + 5,意思就是排从 arr[0] 到 arr[4] 这 5 个元素。
例2:考试分数从高到低排名(降序)
默认 sort 是从小到大(升序),但我们有时想要从大到小(降序),比如看谁分数最高。这时候需要第三个参数——一个“排序规则”。
C++ 已经为你准备好了 greater<int>() 这个工具,意思是“越大的越往前”。
#include <iostream>
#include <vector>
#include <algorithm> // sort 和 greater 都在这里
using namespace std;
int main() {
// 存储一次数学考试的成绩
vector<int> scores = {88, 95, 70, 100, 82};
// 从大到小排序,greater<int>() 就是“越大越靠前”的规则
sort(scores.begin(), scores.end(), greater<int>());
cout << "成绩从高到低:";
for (int score : scores) { // C++11 范围for循环,省心又安全
cout << score << " ";
}
cout << endl; // 输出:100 95 88 82 70
return 0;
}
如果想从小到大,既可以不写第三个参数,也可以写 less<int>()(表示“越小越靠前”)。不过默认就是 less<int>(),所以平时不写也行。
区间范围:理解“起始”和“结束”
sort 的区间是 左闭右开 的,也就是包括起始元素,但不包括结束元素。这个概念初学者容易搞混,我们仔细看一下:
- 对数组
int a[10],sort(a, a+5)排的是a[0]到a[4](共5个元素),a[5]及之后的不动。 - 对 vector
v,sort(v.begin(), v.end())排所有元素;如果只想排前3个,可以写sort(v.begin(), v.begin()+3)。 - 也可以只排中间一段:比如
sort(v.begin()+2, v.begin()+5)排第3个到第5个元素(索引2,3,4)。
形象记忆:把 begin 当作你手指的起点,end 是你手指停下的地方,但不会碰到那本书。
新手容易犯的错误(快来避坑)
-
忘记包含头文件
#include <algorithm>没写,编译器会报错:“找不到 sort 函数”。就像做菜没拿锅铲一样。 -
结束地址写错了
对数组int a[100],如果写sort(a, a+100)是对的(排 100 个元素)。
但初学者可能会写成sort(a, a+99),那就只排了前 99 个,最后一个没进去。
或者写成sort(a, a+101),数组越界,程序可能崩溃。 -
对 vector 用指针
vector 的迭代器不是普通指针,不能用v或者v+5当作起始地址。一定要用v.begin()和v.end()。
错误示范:sort(v, v+5);这是不行的。 -
降序时忘记加括号
greater<int>()是一个函数对象,后面的括号不能省。写成greater<int>不带括号是错误的,编译器会以为你在说类型而不是对象。 -
自定义类型没有比较规则
如果 vector 里存的是你自己定义的结构体(比如学生、书籍),sort不知道按哪个字段排,会报错。这时就需要写自定义比较函数(后面有介绍)。
完整示例:按零食价格排序(升序 + 降序)
下面是一个完整的程序,它创建了一个 vector 存储几种零食的价格,先按从低到高排序,再按从高到低排序,并输出结果。
#include <iostream>
#include <vector>
#include <algorithm> // 包含 sort 和 greater
using namespace std;
int main() {
// 零食价格(单位:元)
vector<int> prices = {3, 7, 1, 10, 5};
cout << "原始价格:";
for (int price : prices) {
cout << price << " ";
}
cout << endl;
// 从小到大排序(默认升序)
sort(prices.begin(), prices.end());
cout << "从低到高排序:";
for (int price : prices) {
cout << price << " ";
}
cout << endl;
// 从大到小排序(用 greater<int>() 降序)
sort(prices.begin(), prices.end(), greater<int>());
cout << "从高到低排序:";
for (int price : prices) {
cout << price << " ";
}
cout << endl;
return 0;
}
输出结果:
原始价格:3 7 1 10 5
从低到高排序:1 3 5 7 10
从高到低排序:10 7 5 3 1
进阶小挑战:自己定规矩(自定义排序)
有时候排序的规则不是简单的数字大小。比如,你想按数字的个位数排序(不管百位十位),或者按姓名长度,甚至按两个条件排名。这时你可以自己写一个“比较函数”,然后作为第三个参数传给 sort。
比较函数的写法是:返回 true 表示第一个参数应该排在第二个参数前面。举个例子,按个位数从小到大排:
// 自定义比较函数:只看个位数
bool cmp_by_last_digit(int a, int b) {
return (a % 10) < (b % 10);
}
// 使用:sort(arr, arr + n, cmp_by_last_digit);
对于中小学生,知道有这种方法就行。等以后学到结构体,就可以用它来排成绩单、排游戏角色等更复杂的数据。
小练习(自己做做看)
- 创建一个 vector,存储你最喜欢的 5 个数字(比如生日、幸运数字等)。
- 用
sort把它们从小到大排序,然后输出。 - 改成
greater<int>()再排序,看看发生了什么变化。
思考:如果 vector 里的数字有重复的,排序后它们会挨在一起吗?试试看!
相关知识点指引
stable_sort:跟sort类似,但是当两个元素相等时,会保持它们原来的相对顺序(即稳定排序)。如果你在排队后还关心先后次序,可以用它。partial_sort:有时候你只想排出前几名,比如全年级成绩的前 10 名,后面的不用排太细。partial_sort可以只排好前几名,后面的随便站。- 手动排序算法:如果不用
sort,你也可以自己写选择排序、冒泡排序或插入排序。虽然慢一些,但能让你更理解排序的每一步是怎么做的——这也是初学者非常重要的基本功。 - 自定义比较函数:对于结构体数组或类容器,需要自己编写比较规则,这样
sort才知道按什么排序。
记住,sort 是目前 C++ 里最方便、最快速的排序工具之一,学好它,以后遇到排序任务就不用发愁啦!
例题精讲
使用sort函数对一个int数组a(大小为10)进行升序排序,以下哪项调用是正确的?
sort函数可以对所有容器类型(如list、vector、deque)进行排序。
以下代码希望将数组arr(int类型,大小n)按从大到小排序,请填空:
#include <algorithm>
#include <functional>
using namespace std;
int arr[] = {3, 1, 4, 1, 5, 9};
int n = sizeof(arr)/sizeof(arr[0]);
sort(arr, arr + n, ___);关于sort函数的时间复杂度,以下哪个描述正确?
sort函数要求排序范围必须是连续的,即[first, last)中的元素可以通过迭代器自增逐个访问。