递归(Recursion)

239 阅读3分钟

递归的概念

递归就是方法自己调用自己,每次调用时传入不同的变量,递归有助于编程者解决复杂的问题,同时可以让代码变得简洁。

  • 递归的分类:
    • 递归分为两种,直接递归和间接递归。
    • 直接递归称为方法自身调用自己。
    • 间接递归可以A方法调用B方法,B方法调用C方法,C方法调用A方法。
  • 注意事项
    • 递归一定要有条件限定,保证递归能够停止下来,否则会发生栈内存溢出。
    • 在递归中虽然有限定条件,但是递归次数不能太多。否则也会发生栈内存溢出。
    • 构造方法,禁止递归
public class DiGuiDemo2 {
    public static void main(String[] args) {
      	// 创建File对象
        File dir  = new File("D:\\aaa");
      	// 调用打印目录方法
        printDir(dir);
    }

    public static void  printDir(File dir) {
      	// 获取子文件和目录
        File[] files = dir.listFiles();
      	// 循环打印
      	/*
      	  判断:
      	  当是文件时,打印绝对路径.
      	  当是目录时,继续调用打印目录的方法,形成递归调用.
      	*/
        for (File file : files) {
    		// 判断
            if (file.isFile()) {
              	// 是文件,输出文件绝对路径
                System.out.println("文件名:"+ file.getAbsolutePath());
            } else {
              	// 是目录,输出目录绝对路径
                System.out.println("目录:"+file.getAbsolutePath());
              	// 继续遍历,调用printDir,形成递归
                printDir(file);
            }
        }
    }
}

递归遍历文件夹及文件并指定后缀输出

package com.snail.test.io;

import java.io.File;

public class Demo1 {
  public static void main(String[] args) {
    File file = new File("/Users/snail/Documents/note");
    getAllFile(file);
  }

  private static void getAllFile(File dir) {
    File[] files = dir.listFiles();
    for (File file : files) {
      if(file.isDirectory()){
        getAllFile(file);
      }else{
        if(file.getName().toLowerCase().endsWith(".txt")){
          System.out.println(file);
        }
      }
    }
  }
}

递归删除指定目录下的所有文件目录

public static void delFile(File file){
    if(file.isDirectory()){
        File[] files = file.listFiles();
        for(File f : files){
            if(f.isFile()){
                f.delete();
            }else if(f.isDirectory()){
                delFile(f)
            }
        }
    }
}

测试代码

package top.snailstudy.recursion;

public class RecursionTest {
    public static void main(String[] args) {
        test(4);
    }
    public static void test(int n){
        if(n > 2){
            test(n -1);
        }
        System.out.println("n="+n);
    }
}

分析图

微信图片_20201223095948.jpg

阶乘实例

package top.snailstudy.recursion;

public class RecursionTest {
    public static void main(String[] args) {
        int i = factorial(6);
        System.out.println(i); //输出 720
    }

    public static int factorial(int n){
        if(n==1){
            return 1;
        }else {
            return factorial(n-1)*n;
        }
    }
}

递归能解决什么样的问题?

  1. 各种数学问题如:8皇后问题,汉若塔,阶乘问题,迷宫问题,球和篮子的问题...
  2. 各种算法中也会使用到递归,比如快排,归并排序,二分查找,分治算法等
  3. 将用栈解决的问题,可以用递归解决代码更简洁

递归需要遵循的重要规则

  1. 执行一个方法时,就创建一个新的受保护的独立空间(栈空间)
  2. 方法的局部变量是独立的,不会相互影响
  3. 如果方法中使用的是引用类型变量,就会共享该引用类型的数据
  4. 递归必须向退出递归的条件逼近,否则就是无限死循环
  5. 当一个方法执行完毕,或者遇到return,就会返回,遵守谁调用,就将结果返回给谁,同时当方法执行完毕或者返回时,该方法也就执行完毕。