归并排序
题目描述
给定你一个长度为n的整数数列。
请你使用归并排序对这个数列按照从小到大进行排序。
并将排好序的数列按顺序输出。
输入格式
输入共两行,第一行包含整数 n。
第二行包含 n 个整数(所有整数均在$1$ ~$ 10^9$范围内),表示整个数列。
输出格式
输出共一行,包含 n 个整数,表示排好序的数列。
数据范围
$1≤n≤1000001≤n≤100000$
输入样例:
输出样例:
题目分析
归并排序相对于快速排序更稳定
- 确定分界点
取中间值mid = (l + r) >> 1
- 归并排序左右两边
- 将左右两边合二为一
- 指针从两边的开头同时开始,取数比较
- 取出最小的放入新数组,指针向后移
- 直到一个指针走到当前段的末尾为止
若某一段指针已到了末尾,另一段指针还在一半,将直接将剩下一半依次放入新数组
- 将新数组值放回原数组
代码实现
#include<iostream> using namespace std;
const int N = 1e6 + 10;
int n; int a[N],temp[N];
void merge_sort(int l, int r, int a[]){ if(l >= r) return; int mid = l + r >> 1; merge_sort(l, mid, a); merge_sort(mid + 1, r, a); int k = 0; int 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(i = l, j = 0; i <= r; i++,j++) a[i] = temp[j]; }
int main(){ scanf("%d", &n); for(int i = 0; i < n; i++) scanf("%d", &a[i]); merge_sort(0, n - 1, a); for(int i = 0; i < n; i++) printf("%d ", a[i]); }
|
运行结果
输入
输出
总结
归并排序与快速排序最大的差距是分界点的问题,其次是对左右两边分别进行归并排序,然后将左右两边的分别比较出来,依次找出最小值,将其顺次放入到新数组里,最终再整合复制到原数组里进行输出。