JAVA-基础-递归

递归,指在当前方法内调用自己的这种现象

public void method(){
    System.out.println(“递归的演示”);
    //在当前方法内调用自己
    method();
}

递归分为两种,直接递归和间接递归。

直接递归称为方法自身调用自己。间接递归可以A方法调用B方法,B方法调用C方法,C方法调用A方法。

计算1-n之间的和 递归方法

public class DiGuiDemo {
    public static void main(String[] args) {
        //计算1~num的和,使用递归完成
        int n = 5;
        int sum = getSum(n);
        System.out.println(sum);
        
    }
    public static int getSum(int n) {
        if(n == 1){
            return 1;
        }
        return n + getSum(n-1);
    }
}

注意:递归一定要有条件限定,保证递归能够停止下来,否则会发生栈内存溢出。

在递归中虽然有限定条件,但是递归次数不能太多。否则也会发生栈内存溢出。

图解

JAVA-基础-递归

       递归打印所有子目录中的文件路径

编写一个方法用来打印指定目录中的文件路径,并进行方法的调用

要求:若指定的目录有子目录,那么把子目录中的文件路径也打印出来

步骤:

 1. 指定要打印的目录File对象

 2. 调用getFileAll()方法

 3. 获取指定目录中的所有File对象

 4. 遍历得到每一个File对象

 5. 判断当前File 对象是否是目录

                          判断结果为true,说明为目录,通过递归,再次调用步骤2的getFileAll()方法

                          判断结果为false,说明是文件,打印文件的路径

public class FileDemo2 {
    public static void main(String[] args) {
        File file = new File("d:\test");
        getFileAll(file);
    }
    //获取指定目录以及子目录中的所有的文件
    public static void getFileAll(File file) {
        File[] files = file.listFiles();
        //遍历当前目录下的所有文件和文件夹
        for (File f : files) {
            //判断当前遍历到的是否为目录
            if(f.isDirectory()){
                //是目录,继续获取这个目录下的所有文件和文件夹
                getFileAll(f);
            }else{
                //不是目录,说明当前f就是文件,那么就打印出来
                System.out.println(f);
            }
        }
    }
}

  

     搜索指定目录中的.java文件(含子目录)

需求:打印指定目录即所有子目录中的.java文件的文件路径

要求:编写一个方法用来打印指定目录中的.java文件路径,并进行方法的调用

若指定的目录有子目录,那么把子目录中的.java文件路径也打印出来

步骤:

         1. 指定要打印的目录File对象

         2. 调用getFileAll()方法,传入要打印的目录File对象

                  2.1 通过FilenameFilter过滤器获取指定目录中的所有.java类型的File对象

                  2.2 遍历得到每一个File对象

                  2.3 判断当前File 对象是否是目录

                          判断结果为true,说明为目录,通过递归,再次调用步骤2的getFileAll()方法

                          判断结果为false,说明是文件,打印文件的路径

 

public class FileDemo4 {
    public static void main(String[] args) {
        File file = new File("d:\test");
        getFileAll(file);
    }
    //获取指定目录以及子目录中的所有的文件
    public static void getFileAll(File file) {
        File[] files = file.listFiles(MyFileFilter());
        //遍历当前目录下的所有文件和文件夹
        for (File f : files) {
            //判断当前遍历到的是否为目录
            if(f.isDirectory()){
                //是目录,继续获取这个目录下的所有文件和文件夹
                getFileAll(f);
            }else{
                //不是目录,说明当前f就是文件,那么就打印出来
                System.out.println(f);
            }
        }
    }
}
//定义类实现文件名称FilenameFilter过滤器
class MyFileFilter implements FilenameFilter{
    public boolean accept(File dir, String name) {
        return name.endsWith(".java");
    }
}

循环和递归

对于for或者while循环,只是将重复的步骤利用循环来处理,循环处理完一个步骤后,又进行下一个类似的步骤,关键点是要找出循环的依据和各步骤的相同点(既要循环的部分),什么情况下要继续循环,什么情况下要终止循环,如此例,从1到max有多少的整数就要循环多少次,这就是此例的循环依据,而此例中进行循环的重复操作是累加;
使用递归时,需先找出重复步骤之间的相同逻辑,然后将这些逻辑实现在一个方法中。


递归是在进行一个步骤,进行到某处时,通过调用自身进行分层,在下一层开始紧接着的下一个步骤,
如果下一层不是定义的最后一层,则会在相同的地方再次分层,直到进入最底层,如上例中,max如果
为5,在进行max为5的这一层操作时,将会运行addByMax(4),分层,下一层的max将为4,此时因为定义了max为1时
才为最底层,所以会继续分层,这时max为3,再分,为2,再分,为1,到达最底层,然后
从最底层开始将各层的结果一次向上传递,回归到最顶层,返回最终结果

所以递归时要注意形成一层一层的结构,一般会采取某种判断的方法,如if,如果不满足要求
,那就调用自身进行递归,此时应注意找出上下层之间的联系(各层相同逻辑的部分),让运算进入下一层,
这样形成上一层调用下一层,比如此例中的 max+addByMax(max-1)
最后注意定义一个最底层,即开始向上回归结果的那一层,最底层将不再调用自身进行递归