文章目录
std::sort
详细解析
std::sort
是 C++ 标准库中的 通用排序函数,用于对 随机访问迭代器(Random Access Iterator) 指向的范围进行 就地排序(原地修改,不创建额外副本)。
1. std::sort
语法
(1)默认排序(升序,使用 <
运算符)
#include <algorithm>
void sort(RandomAccessIterator first, RandomAccessIterator last);
- 参数:
first
:排序范围的起始迭代器(包含)。last
:排序范围的结束迭代器(不包含)。
- 默认按照
<
进行升序排序。
(2)自定义比较函数
void sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp);
- 参数:
comp
:比较函数(返回true
表示前者应排在前面)。
示例:
std::sort(vec.begin(), vec.end(), std::greater<int>()); // 降序排序
2. std::sort
示例
(1)对 std::vector
进行升序排序
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> vec = {5, 2, 8, 1, 3};
std::sort(vec.begin(), vec.end());
for (int num : vec) {
std::cout << num << " ";
}
return 0;
}
输出:
1 2 3 5 8
(2)自定义排序(降序)
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> vec = {5, 2, 8, 1, 3};
std::sort(vec.begin(), vec.end(), std::greater<int>());
for (int num : vec) {
std::cout << num << " ";
}
return 0;
}
输出:
8 5 3 2 1
(3)对 std::pair
按照第一个元素排序
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<std::pair<int, char>> vec = {{3, 'C'}, {1, 'A'}, {2, 'B'}};
std::sort(vec.begin(), vec.end());
for (const auto& p : vec) {
std::cout << p.first << p.second << " ";
}
return 0;
}
输出:
1A 2B 3C
- 默认按照
pair
的first
进行排序(std::pair
具有默认<
操作符)。
(4)自定义比较函数
#include <iostream>
#include <vector>
#include <algorithm>
bool customComparator(const std::pair<int, char>& a, const std::pair<int, char>& b) {
return a.second < b.second; // 按字符升序排序
}
int main() {
std::vector<std::pair<int, char>> vec = {{3, 'C'}, {1, 'A'}, {2, 'B'}};
std::sort(vec.begin(), vec.end(), customComparator);
for (const auto& p : vec) {
std::cout << p.first << p.second << " ";
}
return 0;
}
输出:
1A 2B 3C
解释:
- 使用
customComparator
按second
(字符)排序。
3. std::sort
的内部实现
C++ 标准库的 std::sort
通常基于 IntroSort(混合排序算法),它结合了:
- 快速排序(QuickSort) —— 当递归深度较小时,使用快速排序(O(n log n))。
- 堆排序(HeapSort) —— 当递归深度超过阈值(~2 * log(n))时,改用堆排序(O(n log n))。
- 插入排序(InsertionSort) —— 当数据量较小时(如 n ≤ 16),使用插入排序(O(n²))。
IntroSort 结合了三种排序的优点:
- 快速排序 通常最快,但最坏情况(已排序数据)可能变成 O(n²)。
- 堆排序 保证最坏情况下 O(n log n)。
- 插入排序 适用于小数组,减少递归开销。
(1)QuickSort(快速排序)
- 选择 “三数中值”(Median of Three) 作为基准值(pivot)。
- 使用 Hoare Partition 或 Lomuto Partition 进行分区。
void quickSort(int arr[], int low, int high) {
if (low < high) {
int pivot = partition(arr, low, high);
quickSort(arr, low, pivot - 1);
quickSort(arr, pivot + 1, high);
}
}
- 当递归深度过大时,切换到 HeapSort。
(2)HeapSort(堆排序)
- 用 最大堆 保证最坏情况下 O(n log n)。
void heapSort(int arr[], int n) {
std::make_heap(arr, arr + n);
std::sort_heap(arr, arr + n);
}
- 在 QuickSort 递归过深时,切换到 HeapSort。
(3)InsertionSort(插入排序)
- 当 子数组长度 ≤ 16 时,使用插入排序。
void insertionSort(int arr[], int n) {
for (int i = 1; i < n; i++) {
int key = arr[i];
int j = i - 1;
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = key;
}
}
- 减少递归开销,提升小规模排序效率。
4. std::sort
时间复杂度
排序算法 | 最优情况 | 平均情况 | 最坏情况 |
---|---|---|---|
快速排序 | O(n log n) | O(n log n) | O(n²) |
堆排序 | O(n log n) | O(n log n) | O(n log n) |
插入排序 | O(n) | O(n²) | O(n²) |
std::sort
保证 O(n log n) 的最坏情况时间复杂度(由于 IntroSort)。- 比
qsort()
更快(因为std::sort
可以内联,避免qsort()
的函数指针调用开销)。
5. std::sort vs
std::stable_sort
函数 | 稳定性 | 时间复杂度 | 适用情况 |
---|---|---|---|
std::sort | ❌ 不稳定 | O(n log n) | 一般情况,最快 |
std::stable_sort | ✅ 稳定 | O(n log² n) | 需要保留相同元素顺序 |
std::sort
不保证相等元素的相对顺序。std::stable_sort
使用归并排序,保证稳定性。
总结
std::sort
是 C++ 的标准排序函数,基于 IntroSort(快速排序 + 堆排序 + 插入排序)。- 时间复杂度 O(n log n),比
qsort()
更快,因为 支持内联。 - 默认升序排序,可 使用自定义比较函数 进行 降序或其他排序方式。
- 适用于随机访问迭代器(如
vector
,array
),但不能用于list
(用list::sort
)。