参考:https://www.cnblogs.com/onepixel/articles/7674659.html
其他排序算法传送门:https://blog.youkuaiyun.com/jkdcoach/article/details/87442482
源码:https://github.com/sunrui849/sort
归并排序
归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。
1.1 算法描述
- 把长度为n的输入序列分成两个长度为n/2的子序列;
- 对这两个子序列分别采用归并排序;
- 将两个排序好的子序列合并成一个最终的排序序列。
1.2 动图演示
1.3特性
采用分治思想,由最小单元依次向上合并,时间复杂度均为n*(log n),但是需要额外的空间 n
1.4代码实现
/**
* 归并排序
* 从小到大
* @param arr
* @return
*/
public static int[] sort(int[] arr) {
if (arr == null || arr.length == 0){
return arr;
}
return sortDG(arr,0,arr.length-1);
}
/**
* 递归排序数据
* @param arr
* @param left
* @param right
* @return
*/
private static int[] sortDG(int[] arr, int left, int right) {
if (left == right){
return arr;//递归终止点,即左右相等时
}
int middle = (left+right)/2;//相当于取中间数向下取整
sortDG(arr,left,middle);
sortDG(arr,middle+1,right);
merge(arr,left,middle,right);
return arr;
}
/**
* 合并两个区间
* @param arr
* @param left
* @param middle
* @param right
* @return
*/
private static int[] merge(int[] arr, int left, int middle, int right) {
int[] newArr = new int[right-left+1];
int newArrIndex = 0;
int leftMinIndex = left;//左区间最小数
int rightMinIndex = middle + 1;//右区间最小数,middle在左区间是闭区间,在右区间是开区间
while (leftMinIndex <= middle && rightMinIndex <= right){//分别将两遍小数插入新数组,直到有一侧取完
if (arr[leftMinIndex] < arr[rightMinIndex]){
newArr[newArrIndex++] = arr[leftMinIndex++];
}else {
newArr[newArrIndex++] = arr[rightMinIndex++];
}
}
//以下两个while为将还未清空一侧加入新数组中
while (leftMinIndex <= middle){
newArr[newArrIndex++] = arr[leftMinIndex++];
}
while (rightMinIndex <= right){
newArr[newArrIndex++] = arr[rightMinIndex++];
}
//更新arr中数据
for (int value : newArr){
arr[left++] = value;
}
return arr;
}