归并排序
题目描述
归并排序是基于归并操作完成的,而一次归并操作是通过两个或两个以上的有序表合并成一个新的有序表完成的。常见的归并排序是2-路归并排序,其核心操作是将一维数组中前后相邻的两个有序序列归并成一个有序序列。
在本题中,读入一串整数,将其使用以上描述的2-路归并排序的方法从小到大排序,并输出。
输入描述
输入的第一行包含1个正整数n,表示共有n个整数需要参与排序。其中n不超过100000。
第二行包含n个用空格隔开的正整数,表示n个需要排序的整数。
输出描述
只有1行,包含n个整数,表示从小到大排序完毕的所有整数。
请在每个整数后输出一个空格,并请注意行尾输出换行。
样例
输入
10
2 8 4 6 1 10 7 3 5 9
输出
1 2 3 4 5 6 7 8 9 10
归并排序简介
不难发现,2-路归并算法的时间复杂度为O(n
log
2
n
\log_2{n}
log2n),且需要和原始数据等数量的辅助空间。递归形式的2-路归并排序算法在形式上比较简洁,但是实用性较差。通常在需要使用归并排序的场合,往往使用非递归形式的归并排序。
与快速排序和堆排序相比,归并排序的特点在于其是一种稳定的排序方法。
概括一下,归并排序稳定,快速,但是代码较长
AC代码
#include<iostream>
#include<cstdio>
using namespace std;
int a[100005],tmp[100005];
//归并排序函数(递归)
void merge_sort(int l,int r){
//分到不能分为止
if(l>=r){
return;
}
int mid=(l+r)>>1;
//递归调用使每一小部分分成更小的两部分
merge_sort(l,mid);
merge_sort(mid+1,r);
int i=l,j=mid+1,k=0;
//将每一个小部分重新合成并排序
while(i<=mid && j<=r){
if(a[i]<=a[j]){
tmp[k++]=a[i];
i++;
} else{
tmp[k++]=a[j];
j++;
}
}
while(i<=mid){
tmp[k++]=a[i];
i++;
}
while(j<=r){
tmp[k++]=a[j];
j++;
}
for(int i=l,j=0;i<=r;i++,j++){
a[i]=tmp[j];
}
}
//不太重要的主函数
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
merge_sort(1,n);
for(int i=1;i<=n;i++){
printf("%d ",a[i]);
}
return 0;
}