1. 排序思路
- 分解数组,每次都一分为二
[8, 4, 2, 6, 7, 1, 9, 3, 20, 18, 11, 15]
[8, 4, 2, 6, 7, 1] [ 9, 3, 20, 18, 11, 15]
[8, 4, 2] [6, 7, 1] [9, 3, 20] [18, 11, 15]
[8, 4] [2] [6, 7] [1] [9, 3] [20] [18, 11] [15]
[8] [4] [2] [6] [7] [1] [9] [3] [20] [18] [11] [15] - 两两合并(有序)数组
[8] [4] [2] [6] [7] [1] [9] [3] [20] [18] [11] [15]
[4, 8] [2] [6, 7] [1] [3, 9] [20] [11, 18] [15]
[2, 4, 8] [1, 6, 7] [3, 9, 20] [11, 15, 18]
[1, 2, 4, 6, 7, 8] [3, 9, 11, 15, 18, 20]
[1, 2, 3, 4, 6, 7, 8, 9, 11, 15, 18, 20]
2. 代码实现
/**
* 归并排序
* 思路:
* 1. 分解数组,每次都一分为二
* [8, 4, 2, 6, 7, 1, 9, 3, 20, 18, 11, 15]
* [8, 4, 2, 6, 7, 1] [ 9, 3, 20, 18, 11, 15]
* [8, 4, 2] [6, 7, 1] [9, 3, 20] [18, 11, 15]
* [8, 4] [2] [6, 7] [1] [9, 3] [20] [18, 11] [15]
* [8] [4] [2] [6] [7] [1] [9] [3] [20] [18] [11] [15]
* 2. 两两合并(有序)数组
* [8] [4] [2] [6] [7] [1] [9] [3] [20] [18] [11] [15]
* [4, 8] [2] [6, 7] [1] [3, 9] [20] [11, 18] [15]
* [2, 4, 8] [1, 6, 7] [3, 9, 20] [11, 15, 18]
* [1, 2, 4, 6, 7, 8] [3, 9, 11, 15, 18, 20]
* [1, 2, 3, 4, 6, 7, 8, 9, 11, 15, 18, 20]
*
* @param array - 要排序的数组
* @return - 排序后数组(不改变原始数组)
*/
// 分割+合并
public static int[] mergeSort(int[] array, int left, int right) {
// 1. 复制数组
int[] sortedArray = new int[array.length];
for (int i = 0; i < array.length; i++) {
sortedArray[i] = array[i];
}
// 2. 分割+合并
if (left < right) {
// 2.1 分解数组,一分为二
// (1)获取分割点下标 mid
int mid = (left + right) / 2;
// (2) 左递归:继续分割+合并
sortedArray = mergeSort(sortedArray, left, mid);
// (3) 右递归:继续分割+合并
sortedArray = mergeSort(sortedArray, mid + 1, right);
// 2.2 有序合并
mergeTwoArrays(sortedArray, left, right, mid);
}
// 3. 返回排好序的数组
return sortedArray;
}
/**
* 合并两个有序数组
* @param array - 原数组
* @param originalLeft - 原数组左端下标
* @param originalRight - 原数组右端下标
* @param mid - 分割点
*/
// 合并有序数组
private static void mergeTwoArrays(int[] array, int originalLeft, int originalRight, int mid) {
// 1. 设置变量:left 和 right 为左右两个数组的遍历指针(从左到右)
int left = originalLeft;
int right = mid + 1;
// 2. 设置临时数组,存放合并后的新有序数组
int[] tempArray = new int[array.length];
int tempIndex = 0;
// 3. 若左右两个数组都有未处理的数据,将两个数组内数据逐个分别比较大小后放入tempArray,先放数值小的
while (left <= mid && right <= originalRight) {
if (array[left] <= array[right]) {
tempArray[tempIndex] = array[left];
left++;
} else {
tempArray[tempIndex] = array[right];
right++;
}
tempIndex++;
}
// 4. 将左边或右边未处理的数值逐个放入tempArray
while (left <= mid) {
tempArray[tempIndex] = array[left];
tempIndex++;
left++;
}
while (right <= originalRight) {
tempArray[tempIndex] = array[right];
tempIndex++;
right++;
}
// 5. 复制tempArray的数据到原数组
left = originalLeft;
tempIndex = 0;
while (left <= originalRight) {
array[left] = tempArray[tempIndex];
tempIndex++;
left++;
}
}