归并排序和快速排序一样都属于分治问题,无非包括三个步骤:
- 分成子问题;
- 递归处理子问题;
- 合并子问题。
归并排序的算法思路:
- 分成子问题(取中点下标mid = l + r,将原数组分成左右两个数组);
- 递归处理子问题(递归处理左右数组);
- 合并子问题:设两个指针 i 和 j,分别从左右数组最左边即 l 和 mid + 1,开始进行比较,较大元素存入中间数组temp[],直到有一个子数组元素比较完,将剩下元素直接放到temp[]中,最后再将temp[]复制回原数组。
C语言代码如下:
#include<stdio.h>
#define N 1000010
int q[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, i = l, j = mid + 1, tem[r - l + 1];
while(i <= mid && j <= r){
if(q[i] <= q[j]) tem[k++] = q[i++];
else tem[k++] = q[j++];
}
while(i <= mid) tem[k++] = q[i++];
while(j <= r) tem[k++] = q[j++];
//将排好序的数组复制回原数组
for(int k = 0, i = l; i <= r; k++, i++) q[i] = tem[k];
}
int main(){
int n;
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]);
return 0;
}