5 归并排序
归并排序基于分治思想将数组分段排序后合并,时间复杂度在最优、最坏与平均情况下均为 \(\Theta (n \log n)\),空间复杂度为 \(\Theta (n)\).
归并排序可以只使用 \(\Theta (1)\) 的辅助空间,但为便捷通常使用与原数组等长的辅助数组.(摘自 OI Wiki)
让我们来模拟一下排序过程:
原序列:\(1 6 2 7 9 2 5 3\)
两两一组:\(16 \ 2 7 \ 9 2 \ 5 3\)。
每一组内进行排序后:\(16 \ 2 7 \ 2 9 \ 3 5\)
两组合并为一组:\(1267 \ 2359\)
两组合并为一组:\(12235679\)
正规的归并排序是先分割成两两一组,再将组内排序,最后合并变成有序的序列。
代码实现
可以参考 OI Wiki 中的实现,通常使用递归、分治的算法。
6 sort 等
对 \(a\) 数组排序其实可以这么写 sort(a+1,a+n+1,xxx);。底层实现为快速排序。
其中的 xxx 是排序方法。可以是自定义的,也可以是别的。比如说:
- 不写:升序排序。
greater<数据类型>():降序排序。cmp:自定义。
在结构体排序时,一般使用运算符重载和 cmp。示例:
bool cmp(node &u,node &v){//node 为结构体类型
if(u.a!=v.a) return u.a<v.a;//按 a 排序
return u.b<v.b;//a 相等,按 b 排序
}
运算符重载也差不多。
当然除了 sort,也有 stable_sort,底层为归并排序。
例题(洛谷 P1177)
题目描述
将读入的 \(N\) 个数从小到大排序后输出。
输入格式
第一行为一个正整数 \(N\)。
第二行包含 \(N\) 个空格隔开的正整数 \(a_i\),为你需要进行排序的数。
输出格式
将给定的 \(N\) 个数从小到大输出,数之间空格隔开。
输入输出样例 #1
输入 #1
5
4 2 4 5 1
输出 #1
1 2 4 4 5
说明/提示
对于 \(20\%\) 的数据,有 \(1 \leq N \leq 10^3\);
对于 \(100\%\) 的数据,有 \(1 \leq N \leq 10^5\),\(1 \le a_i \le 10^9\)。
看到 \(n \le 10^5\),我们就要用归并排序或其他方法解决。虽然直接 sort 能过。
示例代码:
#include<bits/stdc++.h>
using namespace std;
int n,a[100005];
int main(){
scanf("%d",&n);
for(int i=1; i<=n; i++){
scanf("%d",&a[i]);
}
stable_sort(a+1,a+n+1);
for(int i=1; i<=n; i++){
printf("%d ",a[i]);
}
return 0;
}
浙公网安备 33010602011771号