一、基本用法与语法
1. 默认升序排序
#include <algorithm>
#include <vector>
std::vector<int> nums{3, 1, 4, 1, 5};
std::sort(nums.begin(), nums.end()); // 结果:1,1,3,4,5
2. 自定义排序规则
// 降序排序
std::sort(nums.begin(), nums.end(), std::greater<int>());
// Lambda表达式(C++11+)
std::sort(nums.begin(), nums.end(), [](int a, int b) {
return a > b; // 自定义比较逻辑
});
二、底层实现原理
1. 核心算法组合
- Introsort(内省排序):
- 快速排序(QuickSort)作为基础
- 递归深度超过阈值时转为堆排序(HeapSort)
- 小数据块(<=16元素)转为插入排序(Insertion Sort)
2. 时间复杂度
- 平均情况:O(N log N)
- 最坏情况:O(N log N)(通过堆排序保证)
- 优于传统快速排序的O(N²)最坏情况
3. 内存访问特征
- 随机访问迭代器:要求支持
operator[]
,适用于vector
/deque
等容器 - 非稳定排序:相等元素可能改变相对顺序(需稳定排序时用
std::stable_sort
)
三、关键特性详解
1. 比较函数要求
- 严格弱序(Strict Weak Ordering):
- 必须满足:
comp(a, a) == false // 非自反性 if comp(a, b) == true, then comp(b, a) == false // 非对称性 if comp(a, b) && comp(b, c), then comp(a, c) // 传递性
- 必须满足:
- 错误示例:
// 错误的比较函数(不满足严格弱序) std::sort(nums.begin(), nums.end(), [](int a, int b) { return a <= b; // 错误!应使用 < 而非 <= });
2. 迭代器有效性
- 排序过程中:所有迭代器失效
- 排序完成后:元素位置改变,但迭代器范围
[begin, end)
保持有效
四、性能优化策略
1. 减少对象拷贝
struct BigObject {
int id;
std::vector<double> data(1000);
};
std::vector<BigObject> objs;
// 优化:使用引用避免拷贝
std::sort(objs.begin(), objs.end(), [](const BigObject& a, const BigObject& b) {
return a.id < b.id;
});
2. 移动语义优化
std::vector<std::string> words{"apple", "banana", "cherry"};
std::sort(words.begin(), words.end(),
[](std::string&& a, std::string&& b) { // C++14通用引用
return a.size() < b.size();
});
3. 内存预排序
std::vector<Person> people(1e6);
std::sort(people.begin(), people.end(),
[](const auto& a, const auto& b) { // C++14泛型lambda
return a.age < b.age;
});
五、特殊场景处理
1. 部分范围排序
std::vector<int> nums{5, 2, 8, 1, 9, 3};
std::sort(nums.begin(), nums.begin() + 3); // 只排序前3个元素
// 结果:2,5,8,1,9,3
2. 多条件排序
struct Task {
int priority;
std::string name;
};
std::vector<Task> tasks;
std::sort(tasks.begin(), tasks.end(), [](const Task& a, const Task& b) {
if(a.priority != b.priority)
return a.priority > b.priority; // 优先级降序
else
return a.name < b.name; // 名称升序
});
3. 自定义结构体排序
struct Point {
int x, y;
bool operator<(const Point& other) const { // 重载运算符
return x*x + y*y < other.x*other.x + other.y*other.y;
}
};
std::vector<Point> points{{1,2}, {3,4}, {0,0}};
std::sort(points.begin(), points.end()); // 按距原点距离升序
六、性能对比测试
1. 不同算法性能对比
#include <algorithm>
#include <chrono>
void testSortPerformance() {
const int N = 1e6;
std::vector<int> data(N);
// 生成随机数据
std::generate(data.begin(), data.end(), std::rand);
// 测试std::sort
auto start1 = std::chrono::high_resolution_clock::now();
std::sort(data.begin(), data.end());
auto end1 = std::chrono::high_resolution_clock::now();
// 测试qsort
auto start2 = std::chrono::high_resolution_clock::now();
qsort(data.data(), data.size(), sizeof(int), [](const void* a, const void* b) {
return *(int*)a - *(int*)b;
});
auto end2 = std::chrono::high_resolution_clock::now();
std::cout << "std::sort: "
<< std::chrono::duration<double>(end1 - start1).count() << "s\n";
std::cout << "qsort: "
<< std::chrono::duration<double>(end2 - start2).count() << "s\n";
}
七、常见错误与调试
1. 无效比较函数
// 错误:可能导致越界访问
std::sort(nums.begin(), nums.end(), [](int a, int b) {
return a >= b; // 应使用 > 而不是 >=
});
2. 迭代器失效
std::vector<int> nums{3,1,4};
auto it = nums.begin();
std::sort(nums.begin(), nums.end());
*it = 5; // 危险!排序后it可能指向错误位置
3. 多线程问题
// 错误:多线程共享数据未同步
std::vector<int> shared_data;
void threadFunc() {
std::sort(shared_data.begin(), shared_data.end()); // 需加锁
}
八、与其他排序算法对比
特性 | std::sort | std::stable_sort | std::partial_sort |
---|---|---|---|
时间复杂度 | O(N log N) | O(N log² N) | O(N log K) |
稳定性 | 否 | 是 | 否 |
内存消耗 | 低 | 较高 | 中等 |
适用场景 | 通用排序 | 需保持相等元素顺序 | 获取前K个元素 |
掌握这些内容后,您将能够:
- 高效使用
std::sort
处理各类数据 - 避免常见排序陷阱
- 根据场景选择最佳排序策略
- 进行性能调优和问题诊断