1. 一个应用场景
2. 概述
- 递归就是方法自己调用自己
- 递归需要遵守的重要规则
- 执行一个方法时,就创建一个新的受保护的独立空间(栈空间)
- 方法的局部变量是独立的,不会相互影响;但如果方法中使用的是引用类型变量(比如数组),就会共享该引用类型的数据
- 递归必须向退出递归的条件逼近,即该函数所处理的数据规模必须在递减,否则就是无限递归,出现 StackOverflowError
- 当一个方法执行完毕,或者遇到return,就会返回,遵守谁调用,就将结果返回给谁,同时当方法执行完毕或者返回时,该方法也就执行完毕
- 理解 - 方法调用
3. 过程
- 当在一个函数运行期间,调用另一个函数时,在运行被调用函数之前,系统需要先完成3件事
- 将所有实参,返回地址等信息传递给被调用函数保存
- 为被调用函数的局部变量分配存储区
- 将控制转移到被调函数的入口
- 从被调用函数返回调用函数之前,系统也应完成3件工作
- 保存被调函数的计算结果
- 释放被调函数的数据区
- 依照被调函数保存的返回地址将控制转移到调用函数
- 当有多个函数构成嵌套调用时,按照"后调用先返回"的原则,上述函数之间的信息传递和控制转移必须通过"栈"来实现,即系统将整个程序运行时所需的数据空间安排在一个栈中,每当调用一个函数,就为它在栈顶分配一个存储区,每当从一个函数退出时,就释放它的存储区,则当前正运行的函数的数据区必在栈顶
4. 案例
4.1 阶乘
public static int factorial(int n) { if(n == 1) return 1; else return factorial(n-1) * n; }
4.2 汉诺塔
public static void move(int dish, char x, char y) { System.out.printf("[%d]: %c -> %c\n", dish, x, y); } public static void hanoi(int n, char a, char b, char c) { if(n == 1) move(n, a, c); else { // 这 [n-1个盘子] 要看作一个整体 hanoi(n-1, a, c, b); // 从a - 借助c - 到b move(n, a, c); hanoi(n-1, b, a, c); // 从b - 借助a - 到c } }
5. 递归能解决什么样的问题
使用 递归 解决问题的思路:[ 规模为n的问题 ] 的解决要借助于 [ 规模为n-1的问题 ] 的解决
- 各种数学问题: 8皇后问题,汉诺塔,阶乘问题,迷宫问题,球和篮子的问题
- 各种算法中也会使用到递归,比如快排,归并排序,二分查找,分治算法等
- 需要用 栈 解决的问题 // 递归代码比较简洁
来源:https://www.cnblogs.com/liujiaqi1101/p/12237680.html