排序算法——归并排序 -基本思想&推导&优化&算法&测试
归并排序基本思想:
利用归并的思想,采用经典的分治策略(将问题分divide成一些小的问题后递归求解,治conquer的阶段则将分的阶段得到的各答案修补在一起,即分而治之)
思路:
1.将序列分成子列 直至无法再分解,对子列排序;
2.将两个有序子列合并成一个有序序列;
3.将该有序序列拷贝至原数组覆盖。
示例:[8,4,5,7,1,3,6,2]
输出:[1,2,3,4,5,6,7,8]
理解:
最后一次合并:
package DataStructureAlgorithm.sort;
import java.util.Arrays;
public class sort_mergeSort {
public static void main(String[] args) {
int[] nums = {8,4,5,7,1,3,6,2};//
mergeSort(nums, 0, nums.length-1);
System.out.println("after mergeSort: "+Arrays.toString(nums));
}
//方法:分+合
public static void mergeSort(int[] arr,int left,int right) {
if(left<right) {
int mid=(left+right)/2;//中间索引
//向左递归分解
mergeSort(arr, left, mid);
//向右递归分解
mergeSort(arr, mid+1, right);
//合并
merge(arr, left, mid, right);
}
}
//方法:合
/**
* @param arr 待排序数组
* @param left 数组的左侧索引
* @param mid 右侧索引
* @param right 中间索引
*/
public static void merge(int[] arr,int left,int mid,int right) {
int[] temp = new int[arr.length];//做中转的数组
// int[] temp = new int[right-left+1];
int i=left;//左边有序序列的初始索引为left
int j=mid+1;//右边有序序列的初始索引为mid+1
int t=0;//temp数组的索引
//比较左右两边有序序列,将更小的值放入temp,并将指针后移,直至有一边处理完毕(索引超过末尾元素的下标)
while(i<=mid&&j<=right) {
if (arr[i]<=arr[j]) {
temp[t++]=arr[i++];
}else {
temp[t++]=arr[j++];
}
}
//完成后只有一边序列还有元素(已经排好序)还未放入temp,将其全部依次拷贝至temp
//每拷贝一个数到temp后 就将指针后移,当i指向左边序列的最后一个数时,该数还未被拷贝 故i<=mid
while(i<=mid) {
temp[t++]=arr[i++];
}
while(j<=right) {
temp[t++]=arr[j++];
}
//将temp数据拷贝至原数组arr,每次只拷贝已合并的数据
t=0;//temp数组的索引
int arrLeft=left;//arr数组索引,从其左侧下标开始
while(arrLeft<=right) {
arr[arrLeft++]=temp[t++];
}
// for (int k = 0; k < temp.length; k++) {
// arr[k+left]=temp[k];
// }
}
}
参考:
https://www.bilibili.com/video/BV1E4411H73v?p=69