一、方法的递归 (Recursion)
1、🔺概念
方法自身调用自身
public static void a(){
a();
}
注: 在实际开发中不建议轻易使用递归,能够使用循环代替递归,尽量使用循环。因为递归很耗费栈内存 。另外,递归使用不当,会发生栈内存溢出错误,导致JVM死掉 (JVM停止工作)。但在极少情况下,不使用递归无法实现 (汉诺塔问题等)。
2、满足条件
(1) 有反复执行过程 (方法自身调用自身)
(2) 有递归出口 (有跳出反复执行过程的条件)
3、🔺递归出口 (结束条件)
(1) 当递归程序没有结束条件时,会发生栈内存溢出错误:StackOverflowError,
所以递归必须要有结束条件。
(2) 递归即使有结束条件,即使结束条件是对的,也有可能发生栈内存溢出错误,因为递归太深了
(3) 栈内存发生错误,只有一个结果,JVM死掉 (JVM停止工作)。
(4) 在实际开发中遇到栈内存溢出错误怎么办?
第一步:先检查结束条件是否正确
第二步:若正确,可调整JVM的栈内存大小 (java -X)
(5) “栗子1”:计算5的阶乘
package javaBasis;
// 计算5的阶乘
public class RecursionTest {
public static void main(String[] args) {
int num = 5;
int result = factorial(num);
System.out.println(num + "的阶乘是" + result);
}
public static int factorial(int n) {
// 若没有结束条件,会发生栈内存溢出错误:StackOverflowError
if (n == 1) {
return 1; // 递归结束条件
}
return n * factorial(n - 1);
}
}
4、🔺典例
(1) 汉诺塔【Hanoi】
- 汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。【源自百度百科】
(唯有递归才能解决汉诺塔问题) - 移动规则:
a、按大小顺序重新摆放到目标柱子上
b、小圆盘在上,大圆盘在下 (小圆盘上不能放大圆盘)
c、一次只能移动一个圆盘 - 代码
package javaRecursion;
public class Hanoi {
public static void main(String[] args) {
Hanoi.move(4, "A", "B", "C");
}
/**
* @param disk 圆盘个数
* @param from 初始石柱A
* @param temp 缓冲石柱B
* @param to 目标石柱C
*/
public static void move(int disk, String from, String temp, String to) {
// 若圆盘只有一个时,将其从A移动到C
if (disk == 1) {
System.out.println("将圆盘" + disk + "从石柱" + from + "移动到石柱" + to);
}
else {
move(disk - 1, from, to, temp);
System.out.println("将圆盘" + disk + "从石柱" + from + "移动到石柱" + to);
move(disk - 1, temp, from, to);
}
}
}
/* 运行结果:
将圆盘1从石柱A移动到石柱B
将圆盘2从石柱A移动到石柱C
将圆盘1从石柱B移动到石柱C
将圆盘3从石柱A移动到石柱B
将圆盘1从石柱C移动到石柱A
将圆盘2从石柱C移动到石柱B
将圆盘1从石柱A移动到石柱B
将圆盘4从石柱A移动到石柱C
将圆盘1从石柱B移动到石柱C
将圆盘2从石柱B移动到石柱A
将圆盘1从石柱C移动到石柱A
将圆盘3从石柱B移动到石柱C
将圆盘1从石柱A移动到石柱B
将圆盘2从石柱A移动到石柱C
将圆盘1从石柱B移动到石柱C
*/
(2) 斐波那契数列【Fibonacci】
兔子问题:假定一对大兔子每月能生一对小兔子,且每对新生的小兔子经过一个月可以长成大兔子,且具备繁殖能力。如果不发生死亡,且每次均生下一雌一雄,问一年后共有多少对兔子?
分析:第一个月兔子没有繁殖能力,所以还是一对;两个月后生下一对小兔子,共有两对;三个月后,老兔子再生下一对,小兔子还没有繁殖能力,所以一共是三对;以此类推,可列出下表:
package javaRecursion;
import java.util.Scanner;
public class Fibonacci {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
// 输入第几个月
int month = input.nextInt();
int sumRabbit = 0;
if (month < 1) {
System.out.println("您输入的月份不合法,请输入大于0的整数。");
return;
}else{
sumRabbit = rabbit(month);
}
System.out.println("第" + month + "个月后共有" + sumRabbit + "对兔子。");
}
public static int rabbit(int month) {
if (month == 1 || month == 2) {
return 1;
}else {
return rabbit(month - 1) + rabbit(month -2);
}
}
}