在C++中,std::sort
是一个用于对容器(如数组、std::vector
等)中的元素进行排序的标准库函数。它的内核实现通常基于高效的排序算法,具体实现可能因编译器和标准库的不同而有所差异,但通常会结合多种排序算法来达到最佳性能。
std::sort
的核心特点
-
时间复杂度:std::sort
的平均时间复杂度为 O(NlogN)O(NlogN),其中 NN 是待排序元素的数量。 -
算法选择:
std::sort
通常结合了多种排序算法:-
快速排序(QuickSort):作为主要算法,快速排序在大多数情况下表现良好。
-
插入排序(Insertion Sort):对于小规模数据(如少于一定数量的元素),插入排序的效率更高。
-
堆排序(HeapSort):在快速排序的递归深度过大时,堆排序作为备用算法,避免快速排序的最坏情况。
-
-
优化:现代实现中,
std::sort
会进行多种优化,例如:-
避免递归过深(使用堆排序作为后备)。
-
对小规模数据使用插入排序。
-
使用三数取中法(median-of-three)或更复杂的策略选择枢轴(pivot),以提高快速排序的效率
-
以下是一个简化的 std::sort
实现思路(伪代码):
template <typename RandomIt, typename Compare>
void sort(RandomIt first, RandomIt last, Compare comp) {
if (first != last) {
// 对小规模数据使用插入排序
if (last - first <= INSERTION_SORT_THRESHOLD) {
insertion_sort(first, last, comp);
} else {
// 快速排序的分区操作
RandomIt pivot = partition(first, last, comp);
// 递归排序
sort(first, pivot, comp);
sort(pivot + 1, last, comp);
}
}
}
分区操作(Partition)
分区是快速排序的核心步骤,通常选择一个枢轴元素,将小于枢轴的元素放在左边,大于枢轴的元素放在右边。现代实现中,通常会使用三数取中法或其他策略来选择枢轴,以避免最坏情况。
插入排序(Insertion Sort)
对于小规模数据,插入排序的效率更高,因为它的常数因子较小,且不需要递归调用。
堆排序(HeapSort)
如果递归深度过大(例如超过某个阈值),std::sort
可能会切换到堆排序,以避免快速排序的最坏情况 O(N2)。
实际实现
在实际的 C++ 标准库实现中(如 GCC 的 libstdc++
或 LLVM 的 libc++
),std::sort
的实现会更加复杂和优化。例如:
-
GCC 的
libstdc++
使用了 Introsort(内省排序),它结合了快速排序、堆排序和插入排序。 -
LLVM 的
libc++
也采用了类似的策略。
使用规则
1. 基本用法
std::sort
的基本用法是对一个范围内的元素进行排序。它需要两个迭代器(表示范围的起始和结束)和一个可选的比较函数。
#include <algorithm> // 包含 sort 函数
#include <vector>
#include <iostream>
int main() {
std::vector<int> vec = {4, 2, 5, 1, 3};
// 默认升序排序
std::sort(vec.begin(), vec.end());
for (int i : vec) {
std::cout << i << " "; // 输出: 1 2 3 4 5
}
return 0;
}
2. 自定义比较函数
如果需要自定义排序规则,可以传递一个比较函数(或 lambda 表达式)作为第三个参数。
#include <algorithm>
#include <vector>
#include <iostream>
int main() {
std::vector<int> vec = {4, 2, 5, 1, 3};
// 降序排序
std::sort(vec.begin(), vec.end(), std::greater<int>());
for (int i : vec) {
std::cout << i << " "; // 输出: 5 4 3 2 1
}
return 0;
}
或者使用 lambda 表达式:
std::sort(vec.begin(), vec.end(), [](int a, int b) {
return a > b; // 降序排序
});
3. 排序自定义对象
如果排序的是自定义对象,需要提供比较函数或重载 <
运算符。
#include <algorithm>
#include <vector>
#include <iostream>
struct Person {
std::string name;
int age;
// 重载 < 运算符
bool operator<(const Person& other) const {
return age < other.age; // 按年龄升序排序
}
};
int main() {
std::vector<Person> people = {{"Alice", 25}, {"Bob", 20}, {"Charlie", 30}};
// 使用重载的 < 运算符排序
std::sort(people.begin(), people.end());
for (const auto& p : people) {
std::cout << p.name << ": " << p.age << std::endl;
}
return 0;
}
4. 排序部分范围
std::sort
可以对容器的一部分进行排序,只需指定起始和结束迭代器。
std::vector<int> vec = {4, 2, 5, 1, 3};
std::sort(vec.begin() + 1, vec.end()); // 只排序第2个元素到最后一个元素
5. 稳定性
std::sort
不是稳定排序(即相等元素的相对顺序可能会改变)。如果需要稳定排序,可以使用 std::stable_sort
。