归并算法
1.原理
归并排序利用的是分治的思想实现的,对于给定的一组数据,利用递归与分治技术将数据序列划分成为越来越小的子序列,之后对子序列排序,最后再用递归方法将排好序的子序列合并成为有序序列。合并两个子序列时,需要申请两个子序列加起来长度的内存,临时存储新的生成序列,再将新生成的序列赋值到原数组相应的位置。
2.分治思想
分治,顾名思义,就是分而治之,将一个大问题分解成小的子问题来解决。小的子问题解决了,大问题也就解决了。分治思想一般都是用递归来实现的。分治是一种解决问题的处理思想,递归是一种编程技巧,这两者并不冲突。而对于递归就是要找到递推公式及终止条件,所以写出归并排序的递推公式 mergeSort(m->n) = merge(mergeSort(m->k),mergeSort(k+1->n)); 当 m=n 时终止。即当我们要对 m->n 之间的数列进行排序,其实可以拆分成对 m->k 之间的数列进行排序,以及对 k+1->n 之间的数列排序,然后将连序排好的的数列进行合并就称为了最终的数列,同样的道理,每一段数列的排序又可以继续往下拆分,形成递归。
3.算法过程如下图

4.代码实现
public class MergeSort { public static void merSort(int[] arr,int left,int right){ if(left<right){ int mid = (left+right)/2; merSort(arr,left,mid);//左边归并排序,使得左子序列有序 merSort(arr,mid+1,right);//右边归并排序,使得右子序列有序 merge(arr,left,mid,right);//合并两个子序列 } } private static void merge(int[] arr, int left, int mid, int right) { int[] temp = new int[right - left + 1];//ps:也可以从开始就申请一个与原数组大小相同的数组,因为重复new数组会频繁申请内存 int i = left; int j = mid+1; int k = 0; while(i<=mid&&j<=right){ if (arr[i] < arr[j]) { temp[k++] = arr[i++]; } else { temp[k++] = arr[j++]; } } while(i<=mid){//将左边剩余元素填充进temp中 temp[k++] = arr[i++]; } while(j<=right){//将右序列剩余元素填充进temp中 temp[k++] = arr[j++]; } //将temp中的元素全部拷贝到原数组中 for (int k2 = 0; k2 < temp.length; k2++) { arr[k2 + left] = temp[k2]; } } public static void main(String args[]){ int[] test = {9,2,6,3,5,7,10,11,12}; merSort(test,0,test.length-1); for(int i=0; i<test.length;i++){ System.out.print(test[i] + " "); } } }
5.(1)归并排序的时间复杂度是多少?
归并排序的执行效率与要排序的原始数组的有序程度无关,所以其时间复杂度是非常稳定的,不管是最好情况、最坏情况,还是平均情况,时间复杂度都是 O(nlogn)。
(2)归并排序的空间复杂度是多少?
归并排序的空间复杂度是 O(n)。
(3)归并排序是稳定的排序算法吗?
归并排序算法稳定性不取决于合并函数 merge()。也就是两个有序子数组合并成一个有序数组的那部分代码,通过分析 merge 函数我们发现,归并排序也是一个稳定的排序算法。

浙公网安备 33010602011771号