一、递归的概念与调用机制
简单的说: 递归就是方法自己调用自己,每次调用时传入不同的变量.递归有助于编程者解决复杂的问题,同时可以让代码变得简洁。
我列举两个小案例:
1.打印问题
test(4)
///
public static void test(int n) {
if (n > 2) {
test(n - 1);
}
System.out.println("n=" + n);
}
内存分析:
输出结果:
递归调用规则:
- 当程序执行到一个方法时,就会开辟一个独立的空间(栈)
- 每个空间的数据(局部变量),是独立的.
分析: 这里为什么会先输出 n = 2?
递归的底层机制是栈,每次递归都会形成一个栈,当最后一个递归栈执行完之后,就会退出返回上一个递归栈。而当程序在一步步进行递归时,如果递归方法中有其他语句,那就先不会执行,而是把递归执行到最后一个递归栈,然后最后一个递归栈执行完之后,才会开始执行递归中的其他语句,然后一步步退回上层递归,同时执行上层递归的另一个语句。比如这里在进行递归时,就会执行test(n - 1)这个语句,System.out.println(“n=” + n)这个语句就先不会执行,当最后一个递归栈判断if (n > 2)为false时,退出递归,然后开始执行方法System.out.println(“n=” + n),随即输出n = 2,然后返回上一层递归,接着执行System.out.println(“n=” + n)方法,输出n = 3.
因此在这段语句中,n初始值为4的话,输出顺序是 2 3 4,因为是把最底层的递归的语句先输出,也就是2,然后在一步步退回上层递归输出语句
另外假设我们在代码上加入else也就是这样
test(4)
///
public static void test(int n) {
if (n > 2) {
test(n - 1);
}else
System.out.println("n=" + n);
}
那么输出结果将会是 ===》n = 2
不会再出现其他数字,这里是因为对于最后一个栈来说n > 2不成立,并不会再进行递归,然后执行else语句,也就是会输出n = 2,然后再返回上一个递归,但是对于上一个递归来说,因为满足if (n > 2)条件,所以并不会执行else语句,所以最终整个代码就只会输出n = 2.
2.阶乘问题
//阶乘
public static int factorial(int n) {
if (n == 1) {
return 1;
} else {
return factorial(n - 1) * n;
}
}
二、递归需要遵守的重要规则
- 执行一个方法时,就创建一个新的受保护的独立空间(栈空间)
- 方法的局部变量是独立的,不会相互影响, 比如n变量
- 如果方法中使用的是引用类型变量(比如数组),就会共享该引用类型的数据.
- 递归必须向退出递归的条件逼近,否则就是无限递归,出现StackOverflowError,死龟了:)
- 当一个方法执行完毕,或者遇到return,就会返回,遵守谁调用,就将结果返回给谁,同时当方法执行完毕或者返回时,该方法也就执行完毕。
三、递归-迷宫问题
说明:
小球得到的路径,和程序员设置的找路策略有关即:找路的上下左右的顺序相关
再得到小球路径时,可以先使用(下右上左),再改成(上右下左),看看路径是不是有变化
测试回溯现象
使用递归回溯来给小球找路
说明
1. map 表示地图
2. i,j 表示从地图的哪个位置开始出发 (1,1)
3. 如果小球能到 map[6][5] 位置,则说明通路找到.
4. 约定: 当map[i][j] 为 0 表示该点没有走过 当为 1 表示墙 ; 2 表示通路可以走 ; 3 表示该点已经走过,但是走不通
5. 在走迷宫时,需要确定一个策略(方法) 下->右->上->左 , 如果该点走不通,再回溯
public class MiGong {
public static void main(String[] args)