归并排序
整体过程:先对对数据以中点进行划分,对左边进行排序处理,在对右边进行排序处理,最后合并
思路解析:
比如针对 3 4 2 1 5 6 0 3
首先找到中点下标为3 即值为1
然后对左边 3 4 2 1 做排序处理,再按照上述求中点方法分为 3 4 和 2 1
把3,4 排序后为3,4 ; 2,1 排序后为1,2
然后执行merge变为1,2,3,4
同理对右边也进行排序处理,合并后为0,3,5,6
然后对整体进行合并merge(合并时是临时将数据放到一个新数组,谁小拷贝谁)
所以为 0,1,2,3,3,4,5,6
代码实现
递归实现
// 递归方法实现
public static void mergeSort1(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
process(arr, 0, arr.length - 1);
}
// arr[L...R]范围上,请让这个范围上的数,有序!
public static void process(int[] arr, int L, int R) {
if (L == R) {
return;
}
// int mid = (L + R) / 2
int mid = L + ((R - L) >> 1);
process(arr, L, mid);
process(arr, mid + 1, R);
merge(arr, L, mid, R);
}
public static void merge(int[] arr, int L, int M, int R) {
int[] help = new int[R - L + 1];
int i = 0;
int p1 = L;
int p2 = M + 1;
while (p1 <= M && p2 <= R) {
help[i++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++];
}
// 要么p1越界,要么p2越界
// 不可能出现:共同越界
while (p1 <= M) {
help[i++] = arr[p1++];
}
while (p2 <= R) {
help[i++] = arr[p2++];
}
for (i = 0; i < help.length; i++) {
arr[L + i] = help[i];
}
}
非递归实现
整体思路
// 非递归方法实现
public static void mergeSort2(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
int N = arr.length;
// 步长
int mergeSize = 1;
while (mergeSize < N) { // log N
// 当前左组的,第一个位置
int L = 0;
while (L < N) {
int M = L + mergeSize - 1;
if (M >= N) {
break;
}
int R = M + Math.min(mergeSize, N - M - 1);
merge(arr, L, M, R);
L = R + 1;
}
// 防止溢出
if (mergeSize > N / 2) {
break;
}
mergeSize <<= 1;
}
}