题目描述
给定你一个长度为 n 的整数数列。
请你使用归并排序对这个数列按照从小到大进行排序。
并将排好序的数列按顺序输出。
输入格式
输入共两行,第一行包含整数 n。
第二行包含 n 个整数(所有整数均在 1∼109 范围内),表示整个数列。
输出格式
输出共一行,包含 n 个整数,表示排好序的数列。
数据范围
$$1≤n≤100000$$
输入样例:
5
3 1 2 4 5
输出样例:
1 2 3 4 5
算法
归并排序
时间复杂度
$$O(nlogn)$$
参考文献
C++ 代码
#include<iostream>
using namespace std;
const int N = 1000010;
int n;
int q[N], temp[N];
void merge_sort(int q[], int l, int r){
if(l>=r)return;
int mid = l+r >> 1; //分界点,取中间的点为分界点
// 对左右两边进行递归排序
merge_sort(q, l, mid), merge_sort(q, mid+1, r);
// 进行归并
int k=0; //用来记录另开的数组的下标
int i = l; // 标记排序好的左边数组的起点
int j = mid+1; // 标记排序好的右边数组的起点
while(i<=mid && j<=r){ // 当左边数组没有结束并且右边数组也没有结束时,即只要有一个数组扫描结束就循环结束
if (q[i]<=q[j]) temp[k++] = q[i++]; // 如果左边数组的最小值小于右边数组的最小值,则取出左边数组的最小值放进另开的数组,并且指针后移
else temp[k++] = q[j++]; // 否则取出右边数组的最小值放进新开的数组,并且将右边数组的指针后移
}
// 如果左边数组没有遍历完(隐含说明右边数组已经遍历完),则剩下的值就是这两者数组中的最大值,直接全部放在新开的数组中
while(i<=mid) temp[k++] = q[i++];
// 如果左边数组没有遍历完(隐含说明左边数组已经遍历完),则剩下的值就是这两者数组中的最大值,直接全部放在新开的数组中
while(j<=r) temp[k++] = q[j++];
//将新开的数组中的值重新赋值到原数组中
//原数组从l开始,r结束;新开的数组每次都是以0开始
for (int i=l, j=0;i<=r;i++,j++) q[i] = temp[j];
}
int main(){
scanf("%d", &n);
for (int i=0;i<n;i++) scanf("%d",&q[i]);
merge_sort(q, 0, n-1);
for (int i=0;i<n;i++) printf("%d ", q[i]);
}