归并排序(熟悉下)
归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之)。
参考:https://www.cnblogs.com/chengxiao/p/6194356.html、
package com.nrsc.sort;
public class MergeSort {
public static void main(String[] args) {
int[] arr = { 49, 38, 65, 97, 23, 22, 76, 1, 5, 8, 2, 0, -1, 22 };
mergeSort(arr, 0, arr.length - 1);
System.out.println("排序后:");
for (int i : arr) {
System.out.println(i);
}
}
/**
* 归并排序
*
* @param arr
* @param left
* @param right
*/
private static void mergeSort(int[] arr, int left, int right) {
if (left < right) {
// 取中间值
int middle = (left + right) / 2;
// 对中间值左边进行排序----不断拆分
mergeSort(arr, left, middle);
// 对中间值右边进行排序----不断拆分
mergeSort(arr, middle + 1, right);
// 将左右两个排好序的数组进行合并
merge(arr, left, middle, right);
}
}
/**
* 左右两个排好序的数组进行合并 这两个数组在原arr中下标分别为
* arr[left~,middle]和arr[middle+1,right]
* 这里必须要非常明确(只有这里明确了,才能知道为什么会有注意点1和3)
*
* @param arr 原始数组
* @param left
* @param middle
* @param right
*/
private static void merge(int[] arr, int left, int middle, int right) {
// 新建一个临时数组用来存放排好序的数
int[] tmp = new int[arr.length];
//注意点1
int ls = left;// 左边数组的第一个下标
int ts = left;// 临时数组tmp的最左边的下标
int rs = middle + 1; // 右边数组的第一个下标
// 当两个数组都没到末尾时,谁小,将谁先放进临时数组tmp
while (ls <= middle && rs <= right) {
if (arr[ls] < arr[rs]) {
tmp[ts++] = arr[ls++];
} else {
tmp[ts++] = arr[rs++];
}
}
//注意点2
// 能走到这里有两种情况,或者ls>middle了,或者rs>right了,
// 也就是左边或右边至少有一个数组已经全部放到新数组tmp里了
// 如果这时候ls<=middle,则此时ls~middle的值比已经放进tmp的数都大,只需将其依次放入tmp就好了
while (ls <= middle) {
tmp[ts++] = arr[ls++];
}
// 同理,如果此时rs<=righe,说明此时rs~right的值比已经放进tmp的数都大,只需将其依次放入tmp就好了
while (rs <= right) {
tmp[ts++] = arr[rs++];
}
//注意点3
// 将tmp数组赋值给arr------tmp是有序数组
while (left <= right) {
arr[left] = tmp[left++];
}
}
}