public static void mergeSort1(int l,int r){
if(l == r){
return;//如果仅有一个数,则该天然有序
}
int m = (l + r)/2;
mergeSort1(l,m);
mergeSort1(m + 1,r);
merge(l,m,r);
}
2.3非递归实现
我们也许听过一句话,任何递归的代码都可以转化为非递归,那么非递归又如何实现呢,看思路:
初始间隔设为1
进入循环,循环跳出条件为当间隔已经倍增到大于数组本身大小是,则已排序完可以跳出。
接下来主要的就是找左中右边界,以便传入merge方法中,唯一要注意的就是不要越界
最后传入即可。
代码如下:
java复制代码
public static void mergeSort2() {
int gap = 1; // 初始间隔为1
// 当gap小于n时,继续合并
for (; gap < n; gap <<= 1) {
for (int i = 0; i < n; i += gap * 2) {
int left = i;
int mid = Math.min(left + gap - 1, n - 1); // 确保mid不会越界
int right = Math.min(mid + gap, n - 1); // 确保right不会越界
merge(left, mid, right);
}
}
}
另外还有一种非递归实现方式,如下(这个思路也很厉害):
java复制代码
public static void mergeSort2(){
for(int l,m,r,step = 1;step < n;step <<= 1){
l = 0;//进入循环条件是左侧仍没有跃出数组
while(l < n){
m = l + step - 1;
if(m + 1 >= n){
break;//即右侧无数字,直接返回进入下一次循环
}
//当右侧有数字为r赋初值
r = Math.min(l + (step << 1) - 1,n - 1);//寻找真正的边界
merge(l,m,r);
l = r + 1;//为下次循环找好左边界
}
}
}
这里我再附上完整代码:
java复制代码
import java.util.Scanner;
public class test {
public static int MAXNUM = 100001;
public static int[] arr = new int[MAXNUM];
public static int[] help = new int [MAXNUM];
public static int n;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
n = scanner.nextInt();
for(int i = 0;i < n;i++){
arr[i] = scanner.nextInt();
}
//mergeSort1(0,n - 1);//递归排序
mergeSort2();//非递归实现排序
for(int i = 0;i < n - 1;i++){
System.out.print(arr[i] + " ");
}
System.out.print(arr[n - 1]);
}
public static void mergeSort1(int l,int r){
if(l == r){
return;//如果仅有一个数,则该天然有序
}
int m = (l + r)/2;
mergeSort1(l,m);
mergeSort1(m + 1,r);
merge(l,m,r);
}
public static void mergeSort2(){
for(int l,m,r,step = 1;step < n;step <<= 1){
l = 0;//进入循环条件是左侧仍没有跃出数组
while(l < n){
m = l + step - 1;
if(m + 1 >= n){
break;//即右侧无数字,直接返回进入下一次循环
}
//当右侧有数字为r赋初值
r = Math.min(l + (step << 1) - 1,n - 1);//寻找真正的边界
merge(l,m,r);
l = r + 1;//为下次循环找好左边界
}
}
}
public static void merge(int l,int m,int r){
int a = l;//左侧指针
int b = m + 1;//右侧指针
int i = l;//这个l适用于往help数组拷贝数字使用
while(a <= m && b <=r){
help[i++] = arr[a] < arr[b] ? arr[a++] : arr[b++];
}
//下面俩个双循环用于如果一侧没数字后,则将另一侧依次按序填入
while(a <= m){
help[i++] = arr[a++];
}
while(b <= r){
help[i++] = arr[b++];
}
//最后再依次拷贝进arr数组
for(i = l;i <= r;i++){
arr[i] = help[i];
}
}
}