递归算法其实就是拆解+归并才是完整的,不能单看把两个有序数组归并,而是学会拆分,我……
递归算法里有个非常烧脑的……大概我脑子不好的递归理解
就是那个双层嵌套的sort递归,我实在无法理解,所以画了个图,来排{9084}这四个数
就是
一开始完全不理解这也能递归??画图后果然清晰多了
打印一共执行了三次原地归并,我却不知道怎么来的……所以……
private static void sort(Comparable[] a, int lo, int hi) {
if (hi <= lo)
return;//检查下标
int mid = lo + (hi - lo) / 2;//确定中间值
sort(a, lo, mid);// 将左边排序
sort(a, mid + 1, hi);// 将右边排序
merge(a, lo, mid, hi);
System.out.println(Arrays.toString(a));
}
所以每一个return或者执行完一次归并就会跳出这层递归而不是单纯的循环执行。
理解这个算法首先要学会拆解,它的确实现了拆解,具体自行意会吧。
接下来上源码
package Chapter2_2.MergeSort;
import java.util.Arrays;
import Chapter2_1.ElementarySorts.Example;
import Chapter2_1.ElementarySorts.Shell;
import edu.princeton.cs.algs4.In;
public class Merge extends Example {
/*
* 原地归并的抽象方法+自顶向下的归并排序
*/
@SuppressWarnings("rawtypes")
private static Comparable[] aux;
/*
* 原地归并的抽象方法 将(一个数组分割为两个)不同的两个有序数组归并到第三个数组中。
*/
public static void merge(Comparable[] a, int lo, int mid, int hi) {
int i = lo, j = mid + 1;// i是左边,j是右边
for (int k = lo; k <= hi; k++) {
aux[k] = a[k];// 将a复制到aux里
}
for (int k = lo; k <= hi; k++) {// 用左边左边要递增,用右边右边要递增
if (i > mid) {
a[k] = aux[j++];
} // 左半边用尽取右半边的元素
else if (j > hi) {
a[k] = aux[i++];
} // 右半边用尽取左半边的元素
else if (less(aux[j], aux[i])) {// 当前元素小于左边的当前元素则取右半边的元素
a[k] = aux[j++];
} else {
a[k] = aux[i++];
}
}
}
public static void sort(Comparable[] a) {
aux = new Comparable[a.length];// 一次性分配空间
sort(a, 0, a.length - 1);
}
private static void sort(Comparable[] a, int lo, int hi) {
if (hi <= lo)
return;//检查下标
int mid = lo + (hi - lo) / 2;//确定中间值
sort(a, lo, mid);// 将左边排序
sort(a, mid + 1, hi);// 将右边排序
merge(a, lo, mid, hi);
System.out.println(Arrays.toString(a));
}
public static void main(String[] args) {
String[] a = In.readStrings();
sort(a);
assert isSorted(a);
show(a);
}
}