定义:
-
时间复杂度:最好O(nlogn)、最差O(nlogn)、平均O(nlogn)
-
空间复杂度:O(n),需要维护另外一个数组
-
稳定否:稳定
-
思想:基于合并两个有序数组实现,将排序的宽度从1开始,每次扩大范围进行合并;体现了分、治、合的思想;
实现:
/**
* 归并排序
*
* @param array 排序数组
* @return 排序结果
*/
public static int[] mergeSort(int[] array) {
// 自下而上非递归的方法实现
int n = array.length;
int[] arr2 = new int[n];
for (int width = 1; width < n; width *= 2) {
// 从每一个元素开始进行合并
for (int left = 0; left < n; left += width * 2) {
int right = Math.min(left + width * 2 - 1, n - 1);
// System.out.println(left + ":" + right); // 测试索引
int m = Math.min(left + width - 1, n - 1);
mergeArr(array, left, m, m + 1, right, arr2);
}
// 整体复制完一次,进行拷贝一次
System.arraycopy(arr2, 0, array, 0, n);
}
return array;
}
/**
* 合并有序数组
*
* @param arr1 目标合并数组
* @param iStart 第一段有序开始索引
* @param iEnd 第一段有序结束索引
* @param jStart 第二段有序开始索引
* @param jEnd 第二段有序结束索引
* @param arr2 放结果的数组
*/
public static void mergeArr(int[] arr1, int iStart, int iEnd, int jStart, int jEnd, int[] arr2) {
int k = iStart;
while (iStart <= iEnd && jStart <= jEnd) {
if (arr1[iStart] > arr1[jStart]) {
arr2[k++] = arr1[jStart];
jStart++;
} else {
arr2[k++] = arr1[iStart];
iStart++;
}
}
if (iStart > iEnd) {
// 说明第一段走完了
for (int i = jStart; i <= jEnd; i++) {
arr2[k++] = arr1[i];
}
}
if (jStart > jEnd) {
// 说明第二段走完了
for (int i = iStart; i <= iEnd; i++) {
arr2[k++] = arr1[i];
}
}
}