今天来搞一搞归并(合并)排序
基本思想
归并排序的主要实现思想是分治策略,
先抛出两个问题,大家在读的过程中分析下为什么归并排序满足下面这两点
1、时间复杂度:T(n)= O(nlogn)
2、合并排序算法是渐进最优算法。
将待排序的数组分为大致相等的两部分,分别对这两部分进行排序,最终将两个排好序的数组合并成一个有序的数组。
接下来我们先来看实现代码,如果可以看明白代码,说明你已经了解了归并算法了。看的时候有疑问也不要紧,我们下面会进行详细的分解详细描述。
代码实现(递归)
/**
* 归并排序(递归写法)
* @param nums 需要排序的数组
* @param left 需排序的起始下标
* @param right 需排序的结束下标
* @return 结果(有序数组)
*/
public int[] mergeSort(int[] nums,int left,int right){
//如果 数组为空或者数组的元素数为1,则认为该数组已经是有序的
if(left < right){
//1、找数组中间位置下标
int mid = (left + right)/2;
//2、对左半部分排序
mergeSort(nums,left,mid);
//3、对有右半部分排序
mergeSort(nums,mid+1,right);
//4、合并
merge(nums,left,mid,right);
}
return nums;
}
/**
* 两个有序数组合并
* @param nums 原数组
* @param left 数组起始下标
* @param mid 数组中间下标
* @param right 数组结束下标
*/
public void merge(int[] nums,int left,int mid,int right){
//1、数组一的起始下标
int i = left;
//2、数组二的起始下标
int j = mid +1;
//3、需要一个临时数组
int[] temp = new int[right - left +1];
int k = 0;
//4、顺序比较两个数组,并将小的值放到临时数组中,直到其中一个数组中的元素都放入临时数组中
while (i<=mid && j<=right){
if(nums[i] <= nums[j]){
temp[k++] = nums[i++];
}else {
temp[k++] = nums[j++];
}
}
//5、将数组一剩余的元素放入临时数组
while (i<=mid ){
temp[k++] = nums[i++];
}
//6、将数组二剩余的元素放入临时数组
while (j<=right){
temp[k++] = nums[j++];
}
//7、将临时数组中的元素copy到原数组中
for (int l = 0; l < temp.length; l++) {
nums[left+l] = temp[l];
}
}
上面注释已经将步骤一一都写了,如果有疑问我们看下详细的图解
大家可以思考下 非递归方式如何实现,以及自然合并排序算法
注:自然合并排序会在下篇文章中介绍,
参考
算法设计与分析 第3版__王晓东编著_北京:清华大学出版社_P330_2014.02_13476624