模板
static final int N = 1000010;static int[] q = new int[N];static int[] tmp = new int[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;while (i <= mid && j <= r) {if (q[i] <= q[j]) tmp[k ++] = q[i ++];else tmp[k ++] = q[j ++];}while (i <= mid) tmp[k ++] = q[i ++];while (j <= r) tmp[k ++] = q[j ++];// 这个for循环是将tmp中的值重新赋值给q// 因为是在递归中,所以并不是无用的,如果删除答案会错误for (int m = l, n = 0; m <= r; m++,n++) {q[m] = tmp[n];}}
思想
- 将数组平均分成两部分(奇数个数的话就是一个为n/2个,一个为n/2+1个)。
- 分别递归地排序数组的这两部分。
- 将排好序的两部分归并成一整块。
方法:重新开辟一个数组空间(tmp),利用双指针的移动,将两部分中更小(或更大)的那个数存到tmp中,再将tmp的值存入q中。 - 时间复杂度为O(nlogn)。
与快排的区别
相同点
都是分治思想
不同点
1. 分界点
快排:随机一个值
归并:数组中间值 (l + r)/2 或者 l + r >> 1
2.最难点
快排:把一个数组划分成两端
归并:把两个有序序列合二为一
合并时用双指针的思想,都指向最小值,然后进行两个指针指向数字的比较,从而进行排序
3. 空间使用
归并排序要使用一个额外的数组帮助合并
