一、概述
递归:指在当前方法内调用自己的现象。
递归的分类:
-
- 递归分为两种,直接递归和间接递归
- 直接递归称为方法自身调用自己
- 间接递归可以 A 方法调用 B 方法,B 方法调用 C 方法,C 方法调用 A 方法。
- 递归分为两种,直接递归和间接递归
注意:
-
- 递归一定要有条件限制,保证递归能够停止下来,否则会发生栈内存溢出。
- 在递归中虽然有限定条件,但是递归次数不能太多,苟泽也会发生栈内容溢出。
- 构造方法,进制递归。
递归导致栈内存溢出的原理:
二、案例
1、递归累加求和
计算 1~ n 的和,n 的累加 = n + (n+1) 的累和,可以把累和的操作定义成一个方法,递归调用。
实现:
1 public class Demo {
2 public static void main(String[] args) {
3 //计算1~num的和,使用递归完成
4 int num = 5;
5 // 调用求和的方法
6 int sum = getSum(num);
7 // 输出结果
8 System.out.println(sum);
9 }
10 /*
11 通过递归算法实现.
12 参数列表:int
13 返回值类型: int
14 */
15 public static int getSum(int num) {
16 /*
17 num为1时,方法返回1,
18 相当于是方法的出口,num总有是1的情况
19 */
20 if(num == 1){
21 return 1;
22 }
23 /*
24 num不为1时,方法返回 num +(num‐1)的累和
25 递归调用getSum方法
26 */
27 return num + getSum(num‐1);
28 }
29 }
代码执行图解:
注意:递归一定要有条件限定,保证递归能够停止下来,次数不要太多,否则会发生栈内存溢出。
2、递归求阶乘
阶乘:所有小于及等于该数的正整数的积。
分析:n! = n * (n-1);
实现:
1 public class DiGuiDemo {
2 //计算n的阶乘,使用递归完成
3 public static void main(String[] args) {
4 int n = 3;
5 // 调用求阶乘的方法
6 int value = getValue(n);
7 // 输出结果
8 System.out.println("阶乘为:"+ value);
9 }
10 /*
11 通过递归算法实现.
12 参数列表:int
13 返回值类型: int
14 */
15 public static int getValue(int n) {
16 // 1的阶乘为1
17 if (n == 1) {
18 return 1;
19 }
20 /*
21 n不为1时,方法返回 n! = n*(n‐1)!
22 递归调用getValue方法
23 */
24 return n * getValue(n ‐ 1);
25 }
26 }
3、递归求年龄
问题:第一个人10,第2个比第1个人大2岁,以此类推,请用递归方式计算出第8个人多大?
实现:
1 public int getAge(int n){
2 /*
3 * 第一个人10,n=1, 结果10
4 * 第二个人12,n=2, 结果10 + 2 getAge(1) + 2
5 * 第三个人14,n=3, 结果10 + 2 + 2 getAge(2) + 2
6 *
7 * 第n个人?,n=?, 结果10 + 2 + 2 ...+ ? getAge(n-1) + 2
8 */
9 if(n==1){
10 return 10;
11 }else{
12 return getAge(n-1) + 2;
13 }
14 }
4、递归—爬台阶问题
问题:有n步台阶,一次只能上1步或2步,共有多少种走法?
实现:
1 public long sum(int n){
2 /*
3 * n==1 1
4 * n==2 2
5 * n==3 最后一步 要么从第1级跨2步,要么从第2级跨1步 把走到第1级的走法 + 走到第2级的走法 sum(1) + sum(2)
6 * n==4 最后一步 要么从第2级跨2步,要么从第3级跨1步 把走到第2级的走法 + 走到第3级的走法 sum(2) + sum(3)
7 * n==5 最后一步 要么从第3级跨2步,要么从第4级跨1步 把走到第3级的走法 + 走到第4级的走法 sum(3) + sum(4)
8 *
9 * n=? 最后一步 要么从第n-2级跨2步,要么从第n-1级跨1步 把走到第n-2级的走法 + 走到第n-1级的走法 sum(n-2) + sum(n-1)
10 */
11 if(n==1 || n==2){
12 return n;
13 }else{
14 return sum(n-1) + sum(n-2);
15 }
16 }
三、递归与文件操作
1、递归打印多级目录
分析:多级目录的打印,就是当目录的嵌套。遍历之前,无从知道到底有多少级目录,所以我们还是要使用递归实现。
实现1:
1 public class DiGuiDemo {
2 public static void main(String[] args) {
3 // 创建File对象
4 File dir = new File("D:\aaa");
5 // 调用打印目录方法
6 printDir(dir);
7 }
8 public static void printDir(File dir) {
9 // 获取子文件和目录
10 File[] files = dir.listFiles();
11 // 循环打印
12 /*
13 判断:
14 当是文件时,打印绝对路径.
15 当是目录时,继续调用打印目录的方法,形成递归调用.
16 */
17 for (File file : files) {
18 // 判断
19 if (file.isFile()) {
20 // 是文件,输出文件绝对路径
21 System.out.println("文件名:"+ file.getAbsolutePath());
22 } else {
23 // 是目录,输出目录绝对路径
24 System.out.println("目录:"+file.getAbsolutePath());
25 // 继续遍历,调用printDir,形成递归
26 printDir(file);
27 }
28 }
29 }
30 }
实现2:
1 //listAllSub()方法的功能是列出一个文件或一个目录及它的下一级
2 public void listAllSub(File dir){
3 if(dir.isDirectory()){
4 File[] listFiles = dir.listFiles();
5 for (File sub : listFiles) {//sub可能是一个文件,也可能是一个文件夹
6 listAllSub(sub);//递归:自己调用自己
7 }
8 }
9 System.out.println(dir);
10 }
2、递归求文件或目录大小
实现:
1 public long getLength(File dir){
2 if (dir != null && dir.isDirectory()) {
3 File[] listFiles = dir.listFiles();
4 if(listFiles!=null){
5 long sum = 0;
6 for (File sub : listFiles) {
7 sum += getLength(sub);
8 }
9 return sum;
10 }
11 }else if(dir != null && dir.isFile()){
12 return dir.length();
13 }
14 return 0;
15 }
3、递归删除文件
实现:
1 public void deleteDir(File file){
2 //如果是文件夹,先把它的下一级删除
3 if(file.isDirectory()){
4 File[] listFiles = file.listFiles();
5 //经过这个foreach循环,可以把file的所有的下一级删除
6 for (File sub : listFiles) {
7 deleteDir(sub);
8 }
9 }
10
11 //文件夹就变成了空文件夹,就可以直接删
12 //如果是文件也可以直接删除
13 file.delete();
14 }