在 C++ 标准库中,sort 函数是实现快速排序的最常用工具。
平均时间复杂度为 O(n log n)
本文将系统梳理一维数组、二维数组的排序方法,以及如何通过自定义比较函数实现复杂排序逻辑。

本文语法非特殊说名则默认采用下头文件与命名空间:
#include <bits/stdc++.h>
using namespace std;


一维数组排序

对于普通数组,sort 的使用非常直观,需要传入起始地址结束地址的后一位

int arr[6] = {5, 2, 8, 1, 9, 3};
sort(arr, arr + 6); // 注意是+6(6个元素)而不是+5.

// 结果:1, 2, 3, 5, 8, 9

关键要点:sort 的第二个参数是结束位置的下一个地址,即 arr + n(n 为元素个数)。


二维数组排序

二维数组的排序根据需求不同,主要有三种处理方式。

展平排序(视为一维)

将整个二维数组在内存中视为连续的一维空间进行排序,会破坏原有的行结构。

int arr[3][4] = {
{3, 1, 4, 1},
{5, 9, 2, 6},
{5, 3, 5, 8}
};

// 总共 12 个元素,从 arr[0] 开始排序
sort(arr[0], arr[0] + 12);

排序结果(所有元素按升序排列,原行列关系打乱):

1 1 2 3
3 4 5 5
5 6 8 9

每行单独排序(保留行结构)

遍历每一行,对每一行分别排序,保持行与行之间的相对顺序。

// 对每一行分别排序
for(int i = 0; i < 3; i++) {
sort(arr[i], arr[i] + 4); // 每行4个元素
}

排序结果(每行内部有序,行间顺序不变):

排序前          排序后
3 1 4 1 → 1 1 3 4
5 9 2 6 → 2 5 6 9
5 3 5 8 → 3 5 5 8

按列排序(自定义排序)

在实际应用中,经常需要按特定列排序(例如按学生成绩排序)。此时需要使用自定义比较函数或 Lambda 表达式。

场景示例
假设有以下学生数据(学号, 分数),目标是按分数升序排列:

学号 分数
1 20
3 10
2 30
4 5

实现代码

int arr[4][2] = {
{1, 20},
{3, 10},
{2, 30},
{4, 5}
};


sort(arr, arr + 4, [](const int* a, const int* b) {
return a[1] < b[1]; // 比较分数(第1列,索引为1)
});
// 使用 Lambda 表达式(匿名函数)按第2列(分数)排序(关于 Lambda 表达式的补充,请参考后续章节)
// 注意:参数类型为 const int*,表示指向一行数组的指针


// 排序结果(按分数升序):
// {4, 5},
// {3, 10},
// {1, 20},
// {2, 30}

注意事项:

  • 比较函数的参数 const int* a 实际上代表二维数组的一行(即 a[0] 是学号,a[1] 是分数)
  • const 修饰符可以省略,但建议保留以确保不修改原数据

多关键字排序(稳定排序扩展)

当主排序字段相同时,需要引入第二关键字。例如:先按分数升序,分数相同则按学号升序。

sort(arr, arr + 4, [](const int* a, const int* b) {
if(a[1] != b[1]) {
return a[1] < b[1]; // 先按成绩(第2列)升序
} else {
return a[0] < b[0]; // 成绩相同,按学号(第1列)升序
}
});

逻辑解析:

  1. 首先比较分数 a[1]b[1]
  2. 如果分数不同,直接返回比较结果
  3. 如果分数相同(else 分支),比较学号 a[0]b[0]

总结

排序需求 方法 时间复杂度 是否改变结构
一维数组 sort(arr, arr+n) O(n log n) -
二维展平 sort(arr[0], arr[0]+总元素) O(n log n) 完全打乱行结构
行内排序 循环 sort(arr[i], arr[i]+m) O(n × m log m) 仅行内有序
按列排序 自定义比较函数/Lambda O(n log n) 整行移动
多关键字排序 自定义比较函数/Lambda O(n log n) 整行移动