思路:(1)数组左半个有序(递归),在右半个位置上有序(递归),让左右所有都有序。merage
(2)设置一个辅助数组存储有序数组
(3)谁数值小就将其拷贝到辅助数组中---直到所有数值拷贝结束
时间复杂度:O(N),指针不会回退。
- 使用递归实现
//递归方法实现
public static void mergeSort1(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
process(arr, 0, arr.length - 1);
}
//arr[L...R]范围上,变成有序的
//L...R N T(N) = 2*T(N/2) + O(N) ->
public static void process(int[] arr, int L, int R) {
if (L == R) {
return;
}
int mid = ((R - L)>>1) + L;
process(arr,L,R);//
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++];
}
//如果越界要么左,要不就是右,只有两者中的一个情况
while (p1 <= M) {//p2越界
help[i++] = arr[p1++];
}
while (p2 <= R) {//p1越界
help[i++] = arr[p2++];
}
for (int i = 0; i < help.length; i++) {
//最后的代码拷贝到arr中
arr[L + i] = help[i];
}
}
}
拓展:比较归并排序与一般排序的优点
O(N^2)要比O(N*logN)优势:大量比较行为浪费空间
每次都可以调整步场来排序相邻的数顺序,这个过程(调整步长)为O(logN) ,随后相邻两组的数据排序为O(N)
so --- 总体的复杂度为:O(N)* O(logN)
- 非递归实现
if (arr == null || arr.length < 2) {
return;
}
int N = arr.length;//总长
//步长
int mergeSize = 1;
while (mergeSize < N) {//logN
//当前左组的第一个位置
int L = 0;
//0...
while (L < M) {
// L...M 左组(mergeSize)
int M = L + mergeSize - 1;//M到达右组的第一个位置
if (M >= N) {//右组的长度不够就跳出来
break;
}
//L...M M+1...R(mergeSize)
int R = Math.min(M + mergeSize, N - 1);//右组可以到达最以后的位置
//不能超过N-1
merge(arr, L, M, R);//
L = R + 1;//左组来到下一个R+1的位置
}
if (mergeSize > N /2) {//防止溢出
break;
}
mergeSize >> 1;//步长*2,不超过N就继续
}
}