c++ sort函数怎么用_c++自定义排序规则

12次阅读

std::sortc++11起中基于随机访问迭代器的泛型排序函数,默认升序、平均O(n log n),支持Lambda/函数指针/functor自定义比较,要求严格弱序,不保证稳定,注意迭代器失效与捕获安全。

c++ sort函数怎么用_c++自定义排序规则

sort 函数的基本调用形式(C++11 及以后)

std::sort 头文件提供的泛型排序函数,要求容器支持随机访问迭代器(如 std::vectorstd::Array、原生数组)。它默认按升序排列,底层是 introsort( + 快 + 插入混合),平均时间复杂度 O(n log n)

最常用写法:

std::vector v = {3, 1, 4, 1, 5}; std::sort(v.begin(), v.end()); // 升序:{1, 1, 3, 4, 5}

注意:v.begin()v.end() 是左闭右开区间,v.end() 不参与排序 —— 这点写错会导致未定义行为。

用 lambda 表达式实现降序或复合排序

自定义排序最常用方式是传入第三个参数:一个可调用对象(lambda、函数指针、functor)。它必须接受两个同类型参数,返回 bool,语义为“第一个参数是否应排在第二个之前”(即 strict weak ordering)。

立即学习C++免费学习笔记(深入)”;

  • 降序排列 int 向量:
    std::sort(v.begin(), v.end(), [](int a, int b) { return a > b; });
  • 字符串长度排序:
    std::vector words = {"hi", "hello", "a"}; std::sort(words.begin(), words.end(), [](const std::string& a, const std::string& b) {     return a.length() < b.length(); }); // {"a", "hi", "hello"}
  • 结构体多级排序(先按 score 降序,相等时按 name 升序):
    struct Student {     std::string name;     int score; }; std::vector students = {{"Alice", 85}, {"Bob", 92}, {"Charlie", 92}}; std::sort(students.begin(), students.end(), [](const Student& a, const Student& b) {     if (a.score != b.score) return a.score > b.score;     return a.name < b.name; });

⚠️ 常见错误:lambda 捕获了局部变量但没声明引用([&]),或对非 const 对象做了修改;返回值不是严格弱序(比如用 替代 ),会触发 std::sort 断言失败或崩溃。

用函数指针或仿函数(functor)替代 lambda

当排序逻辑复用频繁、或需保持状态时,函数指针或 functor 更合适。注意函数签名必须匹配:bool(Args...),且不能是重载函数名(编译器无法推导)。

函数指针示例:

bool cmp_desc(int a, int b) { return a > b; } std::sort(v.begin(), v.end(), cmp_desc);

Functor 示例(带状态的比较器):

struct ByMod {     int mod;     ByMod(int m) : mod(m) {}     bool operator()(int a, int b) const {         return (a % mod) < (b % mod);     } }; std::sort(v.begin(), v.end(), ByMod(3)); // 按模 3 的余数升序

⚠️ functor 必须定义 operator()const 成员函数,否则 std::sort 内部可能因临时拷贝导致调用失败。

注意事项:稳定性、迭代器失效与自定义类型

std::sort 是不稳定的(相同元素相对顺序可能改变);如需稳定排序,改用 std::stable_sort

  • 排序过程中,容器内元素会被移动/交换,因此所有指向这些元素的原始指针、引用、迭代器(除用于调用的 begin/end)全部失效 —— 别在排序后继续用它们访问数据。
  • 自定义类型必须提供可比较的字段,且比较逻辑不能依赖未初始化成员或外部全局状态(否则排序结果不可预测)。
  • std::liststd::forward_list,不能直接用 std::sort(不满足随机访问),应改用其成员函数 sort()

真正容易被忽略的是:lambda 捕获列表和参数 const 引用的组合——尤其处理大对象时,漏掉 const& 会导致不必要的拷贝;而过度捕获(比如 [=] 捕获整个 vector)可能引发悬垂引用。

text=ZqhQzanResources