[算法]递归算法中sort的递归理解以及原地归并和自顶向下递归排序
2018-03-19 22:24
302 查看
递归算法其实就是拆解+归并才是完整的,不能单看把两个有序数组归并,而是学会拆分,我……
递归算法里有个非常烧脑的……大概我脑子不好的递归理解
就是那个双层嵌套的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);
}
}
递归算法里有个非常烧脑的……大概我脑子不好的递归理解
就是那个双层嵌套的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);
}
}
相关文章推荐
- PCA降维算法总结以及matlab实现PCA(个人的一点理解)
- Sort-Merge Joins(归并连接算法)
- 8皇后以及N皇后算法探究,回溯算法的JAVA实现,递归方案
- 二叉树的遍历算法(先序中序后序遍历的递归算法与非递归算法、层级遍历的递归与非递归算法)
- 算法实战之递归(2)(递归算法深层次总结)
- 理解使用递归及堆栈的算法处理八皇后问题
- 算法导论—快排及优化以及和STL sort 的比较
- Win32非递归遍历和搜索文件以及目录算法
- java实现四则运算,难点主要在理解加减乘除优先级以及使用递归
- 原地归并算法
- 一个比较容易理解的归并排序--递归实现
- PCA降维算法总结以及matlab实现PCA(个人的一点理解)
- block swaping 原地归并排序的基础(in-place parallel merge sort)
- 初学者:对于FOWGA算法的理解以及将其和蚁群算法相结合的预测
- list容器的特殊sort()算法:非递归--归并排序
- HMM理解以及相关算法
- 关于希尔算法的理解以及两种不同的移动方式
- STL:原地归并排序模板(InplaceMergeSort)
- 深入理解递归以及汉诺塔问题[数据结构]
- 归并算法的JS实现及分析(分治,递归,归并)