std::sort基于Introsort实现,兼具快排的高效、堆排序的最坏情况保障和插入排序的小数据优势,平均时间复杂度为O(N log N),适用于vector等支持随机访问迭代器的容器。通过提供自定义比较器(如lambda表达式或函数对象),可实现升序、降序及多级排序逻辑,广泛应用于数据预处理、算法竞赛和业务排序场景;使用时需注意避免对象拷贝、选择合适容器、简化比较逻辑,并遵循严格弱序原则以确保正确性,必要时可结合std::stable_sort保证相等元素的相对顺序。

C++中,使用STL的
std::sort
要使用
std::sort
<algorithm>
最常见的场景是升序排序,例如对一个
std::vector<int>
#include <iostream>
#include <vector>
#include <algorithm> // 包含 std::sort
int main() {
// 对 std::vector 进行升序排序
std::vector<int> numbers = {5, 2, 8, 1, 9, 3};
std::sort(numbers.begin(), numbers.end());
// 输出: 1 2 3 5 8 9
for (int n : numbers) {
std::cout << n << " ";
}
std::cout << std::endl;
// 对 C 风格数组进行升序排序
int arr[] = {7, 4, 0, 6, 2};
std::sort(arr, arr + 5); // arr + 5 是指向数组末尾之后一个元素的指针
// 输出: 0 2 4 6 7
for (int i = 0; i < 5; ++i) {
std::cout << arr[i] << " ";
}
std::cout << std::endl;
return 0;
}如果你需要降序排序,或者有更复杂的排序逻辑,
std::sort
bool
立即学习“C++免费学习笔记(深入)”;
例如,降序排序:
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional> // 包含 std::greater
int main() {
std::vector<int> numbers = {5, 2, 8, 1, 9, 3};
// 使用 lambda 表达式进行降序排序
std::sort(numbers.begin(), numbers.end(), [](int a, int b) {
return a > b; // 如果 a 大于 b,则认为 a 在排序上“小于”b(即排在b前面)
});
// 输出: 9 8 5 3 2 1
for (int n : numbers) {
std::cout << n << " ";
}
std::cout << std::endl;
// 或者使用 std::greater<int>() 函数对象
std::vector<int> moreNumbers = {10, 20, 5, 15};
std::sort(moreNumbers.begin(), moreNumbers.end(), std::greater<int>());
// 输出: 20 15 10 5
for (int n : moreNumbers) {
std::cout << n << " ";
}
std::cout << std::endl;
return 0;
}对于自定义数据类型,比如一个结构体,你可以根据其成员变量来排序:
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
struct Student {
std::string name;
int score;
int id;
};
int main() {
std::vector<Student> students = {
{"Alice", 95, 101},
{"Bob", 88, 103},
{"Charlie", 95, 102},
{"David", 72, 100}
};
// 按分数降序排序,如果分数相同,则按ID升序排序
std::sort(students.begin(), students.end(), [](const Student& a, const Student& b) {
if (a.score != b.score) {
return a.score > b.score; // 分数高的排前面
}
return a.id < b.id; // 分数相同,ID小的排前面
});
for (const auto& s : students) {
std::cout << "Name: " << s.name << ", Score: " << s.score << ", ID: " << s.id << std::endl;
}
/*
输出:
Name: Alice, Score: 95, ID: 101
Name: Charlie, Score: 95, ID: 102
Name: Bob, Score: 88, ID: 103
Name: David, Score: 72, ID: 100
*/
return 0;
}说实话,
std::sort
首先是效率。它的平均时间复杂度是O(N log N),这在理论上已经是比较好的了。更关键的是,大多数STL实现都用了Introsort,这玩意儿很聪明,它会根据数据规模和特性,在快速排序、堆排序和插入排序之间切换。这意味着你既能享受到快排在平均情况下的极速,又能避免快排在最坏情况(比如数据已经几乎有序或逆序)下退化成O(N^2)的尴尬。而堆排序则保证了最坏情况下的O(N log N)性能,小数据量时插入排序又很高效。这种混合策略,在我看来,比你手动实现任何一种单一排序算法都要来得稳健和高效。
其次是通用性和易用性。它不挑容器,只要你的容器能提供随机访问迭代器(比如
std::vector
std::deque
std::sort
begin()
end()
再来是灵活性。通过自定义比较器,
std::sort
至于应用场景,那可就多了。
std::sort
std::sort
当然,这里也要提一下
std::stable_sort
std::stable_sort
std::sort
std::stable_sort
std::sort
std::sort
std::stable_sort
尽管
std::sort
无论做任何事情,都要有一定的方式方法与处理步骤。计算机程序设计比日常生活中的事务处理更具有严谨性、规范性、可行性。为了使计算机有效地解决某些问题,须将处理步骤编排好,用计算机语言组成“序列”,让计算机自动识别并执行这个用计算机语言组成的“序列”,完成预定的任务。将处理问题的步骤编排好,用计算机语言组成序列,也就是常说的编写程序。在Pascal语言中,执行每条语句都是由计算机完成相应的操作。编写Pascal程序,是利用Pasca
4
常见的性能陷阱:
const &amp;
std::vector<MyBigStruct>
MyBigStruct
std::sort
std::list
std::list
std::sort
std::list
std::vector
std::vector
优化策略:
const &amp;
const &amp;
// 错误示例 (可能导致拷贝)
// std::sort(vec.begin(), vec.end(), [](MyObject a, MyObject b) { return a.value < b.value; });
// 正确示例 (避免拷贝)
std::sort(vec.begin(), vec.end(), [](const MyObject& a, const MyObject& b) { return a.value < b.value; });std::vector
std::sort
std::vector
std::sort(std::execution::par, begin, end, comparator);
std::sort
std::vector
vector
vector::reserve()
编写一个高效且正确的比较函数,是充分发挥
std::sort
核心原则:严格弱序(Strict Weak Ordering)
任何用于
std::sort
comp(a, a)
false
comp(a, b)
true
comp(b, a)
false
comp(a, b)
true
comp(b, c)
true
comp(a, c)
true
a
b
comp(a, b)
comp(b, a)
false
b
c
a
c
如果你违反了这些规则,
std::sort
编写技巧:
优先使用Lambda表达式:在现代C++中,lambda表达式是编写比较函数的首选。它们简洁、可以直接在调用
std::sort
struct Item {
std::string name;
int value;
double weight;
};
std::vector<Item> items = { /* ... */ };
double threshold = 10.0; // 假设需要根据某个外部阈值进行排序
std::sort(items.begin(), items.end(), [threshold](const Item& a, const Item& b) {
// 示例:先按 value 降序,如果 value 相同,再按 weight 升序,
// 并且如果 weight 小于 threshold,则认为它“更小”
if (a.value != b.value) {
return a.value > b.value; // value 降序
}
// value 相同,考虑 weight
if (a.weight < threshold && b.weight >= threshold) {
return true; // a 的 weight 小于 threshold,b 不小于,a 优先
}
if (a.weight >= threshold && b.weight < threshold) {
return false; // b 的 weight 小于 threshold,a 不小于,b 优先
}
return a.weight < b.weight; // 都小于或都不小于 threshold,按 weight 升序
});这个例子稍微复杂一点,但它展示了lambda的强大之处,能够捕获
threshold
多级排序的链式比较:这是处理复杂排序逻辑的常用模式。当你需要根据多个条件进行排序时,通常会先比较第一个条件,如果相等,再比较第二个条件,以此类推。
// 假设 Student 结构体如前所述:name, score, id
std::sort(students.begin(), students.end(), [](const Student& a, const Student& b) {
if (a.score != b.score) {
return a.score > b.score; // 主排序键:分数降序
}
// 分数相同,进入次排序键:ID 升序
return a.id < b.id;
});这种模式是严格弱序的天然体现,因为它明确定义了当主键相等时,如何通过次键来区分元素。
使用函数对象(Functor):当你的比较逻辑非常复杂,或者需要维护一些状态时,函数对象(即重载了
operator()
class CustomStudentComparator {
public:
// 构造函数可以接受一些状态参数
CustomStudentComparator(int min_score_priority = 0) : min_score_priority_(min_score_priority) {}
bool operator()(const Student& a, const Student& b) const {
// 示例:分数高于某个阈值的优先,然后按分数降序,最后按ID升序
bool a_high_score = (a.score >= min_score_priority_);
bool b_high_score = (b.score >= min_score_priority_);
if (a_high_score != b_high_score) {
return a_high_score; // 高分优先
}
if (a.score != b.score) {
return a.score > b.score; // 分数降序
}
return a.id < b.id; // ID升序
}
private:
int min_score_priority_;
};
// 使用:
// std::sort(students.begin(), students.end(), CustomStudentComparator(90));这种方式在需要将比较逻辑封装起来,或者需要在运行时
以上就是C++如何使用STL排序算法sort的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号