归并排序
主要思想:将集合不断拆分,排序并合并的过程
时间复杂度稳定O(NlogN)
package com.jason.sort;
/**
* @program: LeetCode
* @description: 归并排序
* @author: CodeDuck
* @create: 2020-07-17 17:25
**/
public class MergeSort {
public static void main(String[] args) {
Integer[] arr = {11, 7, 18, 3, 5, 4, 10, 9};
mergeSort(arr);
for (Integer a : arr) {
System.out.println(a);
}
}
// 类型 T 必须实现 Comparable 接口,并且这个接口的类型是 T 或 T 的任一父类,T 的实例和它的父类的实例之间,可以相互比较大小
public static <T extends Comparable<? super T>> void mergeSort(T[] arr) {
// 在排序前,先建好一个长度等于原数组长度的临时数组,避免递归中频繁开辟空间
T[] tmpArr = (T[]) new Comparable[arr.length];
mergeSort(arr, tmpArr, 0, arr.length - 1);
}
// 实现 拆分操作(从左至右进行拆分)
private static <T extends Comparable<? super T>> void mergeSort(T[] arr, T[] tmpArr, int left, int right) {
if (left < right) {
int mid = (left + right) / 2;
mergeSort(arr, tmpArr, left, mid); // 左边归并排序,使得左子序列有序
mergeSort(arr, tmpArr, mid + 1, right); // 右边归并排序,使得右子序列有序
merge(arr, tmpArr, left, mid, right); // 将两个有序子数组合并操作
}
}
private static <T extends Comparable<? super T>> void merge(T[] arr, T[] tmpArr, int left, int mid, int right) {
int i = left; // 左序列指针
int j = mid + 1; // 右序列指针
int t = 0; // 临时数组指针
while (i <= mid && j <= right) {
if (arr[i].compareTo(arr[j]) <= 0) {
tmpArr[t++] = arr[i++];
} else {
tmpArr[t++] = arr[j++];
}
}
while (i <= mid) { // 将左边剩余元素填充进tmpArr中
tmpArr[t++] = arr[i++];
}
while (j <= right) { // 将右序列剩余元素填充进tmpArr中
tmpArr[t++] = arr[j++];
}
t = 0;
// 将tmpArr中的元素全部拷贝到原数组中
while (left <= right) {
arr[left++] = tmpArr[t++];
}
}
}