什么是递归排序
归并排序(Merge Sort)是一种基于分治思想的排序算法,它的基本思想是将待排序的序列不断地分割成两个子序列,直到每个子序列只有一个元素,然后再将这两个子序列合并成一个有序的序列。
归并排序的基本步骤如下:
将待排序的序列不断地分割成两个子序列,直到每个子序列只有一个元素。
对每个子序列进行排序,可以使用任何一种排序算法,例如插入排序、选择排序、快速排序等。
将排好序的子序列合并成一个有序的序列。
归并排序的时间复杂度为 O(nlogn),其中 n 是待排序序列的长度。
递归方式实现归并排序
public static void mergeSort(int[] arr){
if (arr == null || arr.length < 2){
return;
}
process(arr,0,arr.length-1);
}
递归写法:
public static void process(int[]arr,int l,int r){
if (l == r){ //base case
return;
}
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 mid,int r){
int p1 = l; //左边数组的起始位置
int p2 = mid + 1; //右边数组的起始位置
int[]help = new int[r - l + 1]; //辅助数组长度等于左右数组之和
int index = 0;
while (p1 <= mid && p2 <= r){
//左右两边进行比较,小的先进辅助数组,指针移到下一位。
help[index++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++];
}
//两个指针会有一个先越界,剩下的继续进辅助数组下面两个循环,只会进一个
while (p1 <= mid){
help[index++] = arr[p1++];
}
while (p2 <= r){
help[index++] = arr[p2++];
}
//辅助数组排好序后,写进原数组。
for (int i = 0; i < help.length;i++){
arr[l+i] = help[i];
}
}
普通的方式实现递归排序
实现思想是,先定好步长,就是分治时,每次要分治的大小,我们开始步长定为1,然后每次步长进行乘以2.
public static void mergeSort2(int[]arr){
if (null == arr || arr.length < 2){
return ;
}
//每次分治的大小,第一次设为1
int mergeSize = 1;
int N = arr.length;
while (mergeSize < N ){
int L = 0;
while(L < N ){
//这个判断是,当步长大于N - L 时,说明现在只有左边数组有数据,右边数组没数据,这时不进行计算,留到下一次
if (mergeSize >= N - L){
break;
}
int M = L + mergeSize - 1;
//右边取值时,要注意边界,有可能mergesize 大于剩下的数量了,因此要取其中最小的值
int R = M + Math.min(mergeSize,N - M - 1);
//这个merge的方法和上面递归的merge的方法是同一个。
merge(arr,L,M,R);
//进行下一个循环
L = R + 1;
}
//这个是为了防止溢出,megsize * 2 后可能会超过int最大值
if (mergeSize > N/2){
break;
}
//乘以2
mergeSize <<= 1;
}
}