理解java递归思想,通过递归实现文件夹下文件的遍历

1.概述

程序调用自身的编程技巧称为递归( recursion)

2.递归思想

  • 递归就是方法里调用自身
  • 在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口
  • 递归算法代码显得很简洁,但递归算法解题的运行效率较低。所以不提倡用递归设计程序。
  • 在递归调用的过程中系统为每一层的返回点、局部量等开辟了栈来存储。递归次数过多容易造成栈溢出等,所以一般不提倡用递归算法设计程序。

3.递归的三个条件

  • 边界条件
  • 递归前进段
  • 递归返回段

    当边界条件不满足时,递归前进;当边界条件满足时,递归返回。

4.递归的优点和缺点

优点
  • 代码更简洁清晰,可读性更好
  • 在树的前序,中序,后序遍历算法中,递归的实现明显要比循环简单得多
缺点
  • 由于递归需要系统堆栈,所以空间消耗要比非递归代码要大很多
  • 调用栈可能会溢出,其实每一次函数调用会在内存栈中分配空间,而每个进程的栈的容量是有限的,当调用的层次太多时,就会超出栈的容量,从而导致栈溢出。->性能
  • 递归中很多计算都是重复的,由于其本质是把一个问题分解成两个或者多个小问题,多个小问题存在相互重叠的部分,则存在重复计算,如fibonacci斐波那契数列的递归实现。->效率
  • 递归由于是函数调用自身,而函数调用是有时间和空间的消耗的:每一次函数调用,都需要在内存栈中分配空间以保存参数、返回地址以及临时变量,而往栈中压入数据和弹出数据都需要时间。->效率

5.下面通过两个示例程序来说明:

5.1使用Java代码求5的阶乘。(5的阶乘=5*4*3*2*1)

package org.android.test;    
/** 
 * 计算5的阶乘(result = 5*4*3*2*1) 
 */  
public class Test01 {  
    public static void main(String[] args) {  
        System.out.println(f(5));  
    }
    //递归的方法   
    public static int f(int n) {  
        if (1 == n)   
            return 1;  
        else   
            return n*(n-1);  
    }  
}  

这里写图片描述
此题中,按照递归的三个条件来分析:

(1)边界条件:阶乘,乘到最后一个数,即1的时候,返回1,程序执行到底;
(2)递归前进段:当前的参数不等于1的时候,继续调用自身;
(3)递归返回段:从最大的数开始乘,如果当前参数是5,那么就是5*4,即5*(5-1),即n*(n-1)

使用Java代码求数列:1,1,2,3,5,8……第40位的数
[java]
package org.wxp.recursion;

5.2求数列:1,1,2,3,5,8……第40位的数

public class Test02{  
    public static void main(String[] args) {  
        System.out.println(f(6));  
    }  

    public static int f(int n ) {  
        if (1== n || 2 == n)   
            return 1;  
        else  
            return f(n-1) + f(n-2);  
    }  
}  

这里写图片描述
此题的突破口在:从第3位数开始,本位数是前两位数的和。要计算第多少位的值,那么就需要将位数作为参数传进方法进行计算。
(1)首先,当位数为1和2时,当前返回的值应该是1;
(2)然后,当位数为3时,返回值应该=2=1+1;
当位数为4时,返回值=3=2+1;
当位数为5时,返回值=5=3+2;
当位数为6时,返回值=8=5+3;
……
(3)由(2)得知,大于等于3的情况下,当前位数(n)的数值=f(n-1)+f(n-2)

6.和循环相比

6.1递归算法:

优点:代码简洁、清晰,并且容易验证正确性。(如果你真的理解了算法的话,否则你更晕)

缺点:运行需要多次调用,增加额外的堆栈处理(还有可能出现堆栈溢出的情况),会对执行效率有一定影响。但是,对于某些问题,如果不使用递归,那将是极端难看的代码。

6.2循环算法:

优点:速度快,结构简单。

缺点:并不能解决所有的问题。有的问题适合使用递归而不是循环。如果使用循环并不困难的话,最好使用循环。

7.Android递归遍历文件夹中指定格式文件

public ArrayList<String> refreshFileList(String strPath) {
        String filename;//文件名
        String suf;//文件后缀
        File dir = new File(strPath);//文件夹dir
        File[] files = dir.listFiles();//文件夹下的所有文件或文件夹
        if (files == null)
            return null;
        for (int i = 0; i < files.length; i++) {
            if (files[i].isDirectory()){      
                System.out.println("---" + files[i].getAbsolutePath());
                refreshFileList(files[i].getAbsolutePath());//递归文件夹!!
            }else {
                filename = files[i].getName();
                int j = filename.lastIndexOf(".");
                suf = filename.substring(j+1);//得到文件后缀
                if(suf.equalsIgnoreCase("amr"))//判断是不是msml后缀的文件
                {
                    String strFileName = files[i].getAbsolutePath().toLowerCase();
                    wechats.add(files[i].getAbsolutePath());//对于文件才把它的路径加到filelist中
                }
            }
        }
        return wechats;
    }

8.java中关于指定文件夹下所有文件的遍历

import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class ListDirectory {
    public static void showDirectory(File file){
        File[] files = file.listFiles();
        for(File a:files){
            System.out.println(a.getAbsolutePath());
            if(a.isDirectory()){
                showDirectory(a);
            }
        }
    }

    public static void main(String[] args) {
    File file = new File("E:\\aaa");    
    showDirectory(file);
    }
}

9.接下来个递归的题目:

第一个人10岁,第二个人比第一个人大2岁,以此类推,用递归方式算出第10个人年龄多大?

package com.test;

public class ComputeAge {
    /**
     * 从递归的三个条件出发: 
     * 1、递归边界    第10个人  
     * 2、递归前进段  每次大2岁 
     * 3、递归返回    return age   
          最终自己调用自己实现
     */
    public static int getComputeAge(int n) {
        int age = 0;
        if (n == 1) {
            age = 10;
        } else {
            age = getComputeAge(n - 1) + 2;
        }
        return age;
    }

    public static void main(String[] args) {
        System.out.println(getComputeAge(10));
    }
}

总的来说,递归在算法中的使用场景较多,大家慢慢体会。

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值