归并排序Merge Sort(其一)自顶向下的递归实现
归并排序 : 使用递归实现自顶向下的归并排序
- 分治(divide-and-conquer)策略:分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之。
- 时间复杂度 : O(NlogN)
- 空间复杂度 : O(N)
- 归并排序的关键:对于两个已经排好序的子数组,怎么进行归并排序使其成为一个有序的数组。
- (设置三个索引,需要定义清楚k;i,j(维护这个定义))
- left , middle, right
基本思想:
先把待排序的数组分成两半,然后把左边的子数组进行排序,再对右边的子数组进行排序,之后再将这两部分归并起来。当我们对左边的子数组和右边的子数组进行排序的时候,我们再分别对左边的子数组和右边的子数组分成两半,然后对每一个部分先排序再归并,对于这每一个部分,我们还是对它们分半之后归并。当分到一定细度时,每一部分只有一个元素了,我们不用排序,它本身就是有序的,只需要对其进行简单的一次归并就好了,归并到上一个层级后再进行归并,归并到一个更高的层级,一层层的向上归并,归并到最后一层时,整个数组就是有序的了。
归并的具体步骤:
需要额外与arr相等的辅助空间copyArr,将待排序的数组元素arr赋值给copyArr,接下来进行归并操作。
设置三个索引:i,j,k;i从copyArr的left开始,j从copyArr的middle+1开始,k为归并索引,指向下一个需要考虑的位置,从arr的left开始进行遍历。当copyArr[i-left]比copyArr[j-left]小时, arr[k] 等于 copyArr[i-left],此时k++,i++。当copyArr[i-left]比copyArr[j-left]大时,arr[k] 等于 copyArr[j-left],此时k++,j++。
/**
* 归并排序
* @param arr
* @param n
*/
public void mergeSort(E[] arr, int n){
mergeSort(arr, 0 ,n-1);
}
/**
* 递归使用归并排序,对arr[l,...,r]的范围进行排序
* @param arr
* @param left
* @param right
*/
private void mergeSort(E[] arr,int left , int right){
if( left >= right){
//递归到底的情况
return;
}
int middle = (left+right)/2;
mergeSort(arr,left,middle);
mergeSort(arr,middle+1,right);
//对于近乎有序的进行判断
if(arr[middle].compareTo(arr[middle+1]) > 0 ){
merge(arr,left,middle,right);
}
//end mergeSort
}
/**
* 将arr[l,...,mid]和arr[mid_1,...,r]两部分进行归并
* @param arr
* @param left
* @param middle
* @param right
*/
private void merge(E[] arr, int left,int middle, int right){
//辅助空间,并进行赋值 :浅复制
E[] copyArr = arr.clone();
for(int i=left; i<=right;i++){
copyArr[i-left] = arr[i];
}
//定义三个索引
int i = left;
int j = middle+1;
int k;//归并索引,下一个需要考虑的位置
for(k = left;k<=right; k++){
//判断索引是否有效
if(i > middle){
//前面的子数组已归并完
arr[k] = copyArr[j-left];
j++;
}else if(j>right){
//后面的子数组已归并完
arr[k] = copyArr[i-left];
i++;
}else if(copyArr[i-left].compareTo(copyArr[j-left]) <0){
//前面的子数组和后面的子数组都没归并完
arr[k] = copyArr[i-left];
i++;
}else{
//copyArr[i-left].compareTo(copyArr[j-left]) >0
arr[k] = copyArr[j-left];
j++;
}
}
}
可参考https://www.cnblogs.com/chengxiao/p/6194356.html(图示和解释很详细)