一、概述

  递归:指在当前方法内调用自己的现象。

  递归的分类

    •  递归分为两种,直接递归间接递归
    •    直接递归称为方法自身调用自己
    •    间接递归可以 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     }

 

 

 

posted on 2019-09-07 17:39  格物致知_Tony  阅读(484)  评论(0编辑  收藏  举报