【C++】std::sort算法的详解

一、基本用法与语法

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::sortstd::stable_sortstd::partial_sort
时间复杂度O(N log N)O(N log² N)O(N log K)
稳定性
内存消耗较高中等
适用场景通用排序需保持相等元素顺序获取前K个元素

掌握这些内容后,您将能够:

  1. 高效使用std::sort处理各类数据
  2. 避免常见排序陷阱
  3. 根据场景选择最佳排序策略
  4. 进行性能调优和问题诊断
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浩瀚之水_csdn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值