- 确定分界点:mid = (1+r) /2 ;
- 递归排序left 左段和 right 右段
- 归并——合二为一
归并的核心
- 双指针法
左指针l指向排好序的左段序列的第一个元素,右指针r指向排好序的右段序列的第一个元素,申明一个临时数组temp,比较两个指针所值的数的较小者,取出第一个较小者放进temp数组中做为temp数组的第一个元素,然后该指针后移,此时该指针所指的元素是该段在剩下元素中的最小值,再次比较两个指针所指向的数的较小者,取出放进temp数组中做为temp数组的第二个元素。以此类推,直到其中一个指针指向某段最后一个元素,退出循环。把另一段中指针未扫描的剩下元素补到temp数组中即可。
关键代码
public static void merge_sort(int q[], int l, int r, int n) {
int[] temp = new int[n]; //临时数组,也是最终答案数组
if (l >= r) //区间中元素为1或者空时直接返回
return;
int mid = (l + r) >> 1; //确定分界点
merge_sort(q, l, mid, n); //左端,n为元素个数
merge_sort(q, mid + 1, r, n); //右端,n为元素个数
int k = 0, i = l, j = mid + 1; //k记录temp数组中已经合并的数的个数
while (i <= mid && j <= r) {
if (q[i] <= q[j]) //比较指针所指向元素,两段中选出较小者
temp[k++] = q[i++];
else
temp[k++] = q[j++];
}
while (i <= mid) //当右指针指向右段的最后一个元素,若左段没有循环完,则把左端当前指针所指的未扫描的元素补到temp数组中
temp[k++] = q[i++];
while (j <= r) //当左指针指向左段的最后一个元素,若右段没有循环完,则把右端当前指针所指的未扫描的元素补到temp数组中
temp[k++] = q[j++];
for (i = l, j = 0; i <= r; i++, j++) {
q[i] = temp[j]; //把temp数组中元素赋值给原q数组
}
}
总结:
归并排序算法,排序和归并都是在递归中实现,相比快速排序算法,归并排序算法稳定,而快速排序算法不稳定,归并的核心在于归并的过程,快排的核心在于调整区间。对于时间复杂度,归并排序算法时间复杂度为O(nlogn);快速排序算法平均时间复杂度为O(nlogn),最差情况下时间复杂度为:O(n^2)