跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

C++ 排序算法核心解析与 STL 实战

C++ 排序算法涵盖 STL 内置函数及手写实现。重点讲解 sort 自定义比较器、归并排序求逆序对、nth_element 找第 k 大元素及 partial_sort 前 k 名场景。结合复杂度分析,帮助开发者根据数据规模与需求选择最优方案。

路由之心发布于 2026/3/26更新于 2026/10/26106 浏览
C++ 排序算法核心解析与 STL 实战

概念

在编程竞赛或工程实践中,排序都是高频考点。掌握不同场景下的最优解法,能显著提升代码效率。下面结合 C++ 标准库和手写实现,梳理一下常见的排序策略。

常见排序类型

  • 普通升降序排列
  • 自定义规则排序
  • 特定元素查找(如第 k 大)

注:本文示例均基于 C++ 语言。

学习路径建议

  1. 常规任务:优先使用 STL 中的 sort 函数,覆盖 90% 的场景。
  2. 求逆序对:归并排序是经典解法。
  3. 找第 k 大/小:快速选择算法(nth_element)效率更高。
  4. 数据范围极小:考虑计数排序等线性时间复杂度方案。

sort 排序

原理与模板

std::sort 默认采用混合排序(Introsort),综合了快速排序、堆排序和插入排序的优势。通过传入比较函数,可以灵活控制排序逻辑。

#include <bits/stdc++.h>
using namespace std;

int main() {
    // 定义数组并读取数据
    vector<int> a(10);
    for(int i = 0; i < 10; i++) scanf("%d", &a[i]);
    
    // 核心排序:默认升序
    sort(a.begin(), a.end());
    
    // 若需降序,可传入 greater<int>()
    // sort(a.begin(), a.end(), greater<int>());
    
    for(int x : a) printf("%d ", x);
    return 0;
}

注意:如果直接对空 vector 进行 scanf 写入会导致越界,务必先 或指定大小。

resize

例题:自定义结构体排序

以'生日排序'为例,当需要按年、月、日多级条件排序,且姓名相同则按 ID 倒序时,必须借助结构体和自定义比较器。

#include<bits/stdc++.h>
using namespace std;

struct stu {
    string name;
    int year, month, day;
    int id;
};

// 自定义比较函数
bool compare(const stu& a, const stu& b) {
    if (a.year != b.year) return a.year < b.year;
    if (a.month != b.month) return a.month < b.month;
    if (a.day != b.day) return a.day < b.day;
    return a.id > b.id; // 完全相同时,ID 大的排前面
}

int main() {
    int n;
    cin >> n;
    vector<stu> a(n);
    for(int i = 0; i < n; i++) {
        cin >> a[i].name >> a[i].year >> a[i].month >> a[i].day;
        a[i].id = i; // 记录输入顺序,用于稳定处理
    }
    
    sort(a.begin(), a.end(), compare);
    
    for(auto t : a) cout << t.name << endl;
    return 0;
}

关键点说明:

  • 结构体存储:当数据包含多种类型(如字符串 + 整数)时,结构体是最合适的容器。
  • 比较函数返回值:返回 true 表示第一个参数应排在第二个参数之前。注意这里不需要修改原序列,只负责比较。
  • 稳定性处理:如果题目要求完全相同的元素保持原有相对顺序,可以在比较函数中增加对原始索引的判断。

归并排序

原理

归并排序采用分治思想:先递归拆分序列,再合并有序子序列。其时间复杂度稳定在 O(n log n),且是稳定排序。

#include<bits/stdc++.h>
using namespace std;

vector<int> a, temp;

void merge_sort(int l, int r) {
    if (l >= r) return;
    int mid = (l + r) / 2;
    merge_sort(l, mid);
    merge_sort(mid + 1, r);
    
    int k = 0, i = l, j = mid + 1;
    while (i <= mid && j <= r) {
        if (a[i] <= a[j]) temp[k++] = a[i++];
        else temp[k++] = a[j++];
    }
    while (i <= mid) temp[k++] = a[i++];
    while (j <= r) temp[k++] = a[j++];
    
    for (int i = l, k = 0; i <= r; i++, k++) a[i] = temp[k];
}

int main() {
    int n;
    cin >> n;
    a.resize(n); temp.resize(n);
    for(int i = 0; i < n; i++) cin >> a[i];
    
    merge_sort(0, n - 1);
    for(int x : a) cout << x << " ";
    return 0;
}

实现细节:

  • 全局数组:将 a 和 temp 设为全局变量,避免递归过程中频繁传递引用,提升性能。
  • 临时空间:temp 用于暂存合并结果,最后再拷回原数组。

计算逆序对数量

逆序对定义为 i < j 且 a[i] > a[j]。在归并排序的合并阶段,如果左半部分的当前元素大于右半部分元素,则左半部分剩余的所有元素都与该右半部分元素构成逆序对。

long long numble = 0;

void merge_sort(int l, int r) {
    if (l >= r) return;
    int mid = (l + r) / 2;
    merge_sort(l, mid);
    merge_sort(mid + 1, r);
    
    int k = 0, i = l, j = mid + 1;
    while (i <= mid && j <= r) {
        if (a[i] <= a[j]) temp[k++] = a[i++];
        else {
            temp[k++] = a[j++];
            numble += (mid - i + 1); // 关键计数逻辑
        }
    }
    while (i <= mid) temp[k++] = a[i++];
    while (j <= r) temp[k++] = a[j++];
    for (int i = l, k = 0; i <= r; i++, k++) a[i] = temp[k];
}

第 k 大/小数与部分排序

nth_element(快速选择)

如果只需要找出第 k 个位置的元素,而不关心其他元素的顺序,nth_element 是最佳选择。它的时间复杂度平均为 O(n)。

#include<bits/stdc++.h>
using namespace std;

int main() {
    int n, k;
    cin >> n >> k;
    vector<int> a(n);
    for(int i = 0; i < n; i++) cin >> a[i];
    
    // 找到第 k 小的位置(下标从 0 开始)
    nth_element(a.begin(), a.begin() + k, a.end());
    cout << a[k] << endl;
    return 0;
}

用法提示:

  • nth_element(begin, nth, end):将第 k 个元素放到 nth 位置,左边小于等于它,右边大于等于它。
  • 若题目要求第 k 大,可配合 greater<int>() 比较器使用。

partial_sort(部分排序)

当需要输出前 k 个元素且它们内部有序时,使用 partial_sort。

#include<bits/stdc++.h>
using namespace std;

int main() {
    int n, m;
    cin >> n >> m;
    vector<int> a(n);
    for(int i = 0; i < n; i++) cin >> a[i];
    
    // 将前 m 个元素排序好,其余乱序
    partial_sort(a.begin(), a.begin() + m, a.end());
    
    for(int x : a) cout << x << " ";
    return 0;
}

总结

需求推荐方法特点
全部排序sort通用,O(n log n)
仅找第 k 个nth_element最快,平均 O(n)
前 k 名且有序partial_sort中等速度,O(n log k)

复杂度对比

算法平均时间最坏时间空间稳定性适用场景
冒泡/选择/插入O(n²)O(n²)O(1)稳定/不稳定小数据量
归并O(n log n)O(n log n)O(n)稳定大数据、链表
快排O(n log n)O(n²)O(log n)不稳定通用
堆排O(n log n)O(n log n)O(1)不稳定内存受限
计数/桶/基数O(n+k)O(n+k)O(n+k)稳定特定数据分布

以上涵盖了 C++ 中排序的核心知识点。实际开发中,优先调用 STL 函数;遇到特殊约束(如逆序对、内存限制)时,再考虑手写算法。

目录

  1. 概念
  2. 常见排序类型
  3. 学习路径建议
  4. sort 排序
  5. 原理与模板
  6. 例题:自定义结构体排序
  7. 归并排序
  8. 原理
  9. 计算逆序对数量
  10. 第 k 大/小数与部分排序
  11. nth_element(快速选择)
  12. partial_sort(部分排序)
  13. 总结
  14. 复杂度对比

更多推荐文章

查看全部
  • 攻防世界 Web 安全题目解题思路汇总
  • ChatGPT、Gemini 与 Spotify 教育版权益介绍
  • 基于 FPGA 开发应用 SATA 硬盘协议详解
  • OpenClaw 全平台卸载指南(Windows/macOS/Linux/npm/pnpm)
  • 零基础入门网络安全与 Web 安全学习路线指南
  • LightRAG 本地部署与 WebUI 应用指南
  • AI 领域为何全面转向 AI Agent 方向?
  • C++ 进阶:从裸指针到智能指针的内存管理进化
  • Python 安全工具与库精选:网络、逆向、Web 等方向
  • 钉钉 Webhook 完全指南
  • AI 时代数据库的融合与智能化演进
  • 基于闲置 Mac Mini 部署 OpenClaw 构建金融 AI 分析助手
  • Mac 修图效率提升指南:Luminar Neo v1.25.1 核心功能实测
  • 基于 ONNX Runtime 的 C# 模型封装与推理实现
  • Rust 异步编程进阶:Tokio 运行时、任务调度与高性能网络架构
  • 使用 Jenkins Pipeline 自动化构建与部署 Java 项目
  • 多语言 Prompt 实践:中文、英文、日文混写技巧
  • 基于 AI 工程文档构建儿童英语学习应用前端示例
  • 基于鸿蒙 Flutter 的智能家居应用开发实战
  • 二分查找算法原理与常见变体实战

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online