java之递归【通俗易懂】
概念
递归:指在当前方法内调用自己。
递归的分类:
- 直接递归:方法直接调用自己。比如方法A调用方法A
- 间接递归:方法间接调用自己。比如A方法调用B方法,B方法调用C方法,C方法调用A方法。
注意事项:
- 递归一定要有结束条件,否则会无限递归,直至栈内存溢出。
- 虽然递归有结束条件,但是递归次数太多,也会发生栈内存溢出。
- 构造方法,禁止递归(直接编译报错,因为如果允许无限new对象,会导致堆内存溢出。)
为什么会栈内存溢出:
代码演示:
public class Demo01DiGui {
	public static void main(String[] args) {
		// a();
		b(1);
	}
	
	/*
	 * 1.递归一定要有条件限定,保证递归能够停止下来,否则会发生栈内存溢出。 
	 * Exception in thread "main"
	 * java.lang.StackOverflowError
	 */
	private static void a() {
		System.out.println("a方法");
		a();
	}
	/*
	 * 2.在递归中虽然有限定条件,但是递归次数不能太多。否则也会发生栈内存溢出。
	 * 4993
	 * 	Exception in thread "main" java.lang.StackOverflowError
	 */
	private static void b(int i) {
		System.out.println(i);
		//i==5000的时候结束递归
		if(i==5000){
			return;
		}
		b(++i);
	}
	/*
	 * 3.构造方法,禁止递归
	 * 编译报错:构造方法是创建对象使用的,不能让对象一直创建下去
	 */
	public Demo01DiGui() {
		//Demo01DiGui();
	}
}
图解:

简单案例A
需求: 求1~n的和
分析:1~n的累计和 = 1 + 2 + 3 +…+ (n-1) + n,可以看成是 n + (n-1) + …+ 3 + 2 + 1。因此可以把累和的操作定义成一个方法,递归调用。
结束条件就是 n = 1。
代码演示:
/**
 * @author layman
 */
public class Demo02Recurison {
    public static void main(String[] args) {
        int s = sum(3);
        System.out.println(s);
    }
    public static int sum(int n){
        // 结束条件
        if(n == 1){
            return 1;
        }
        return n + getSum(n-1);
    }
}
原理图解

简单案例B
需求:求1~n的阶乘
分析:1~n的阶乘= 1 * 2 * 3 … (n-1) * n,可以看成是 n * (n-1) * …* 3 * 2 * 1。因此可以把累和的操作定义成一个方法,递归调用。
结束条件就是 n = 1。
代码演示:
/**
 * @author layman
 */
public class Demo01 {
    //计算n的阶乘,使用递归完成
    public static void main(String[] args) {
        int n = 20;
        long value = getJC(n);
        System.out.println("n的阶乘为:"+ value);
    }
    /**
    * 通过递归实现n的阶乘
    */
    public static long getJC(int n) {
        if (n == 1) {
            return 1;
        }
        return n * getJC(n - 1);
    }
}
简单案例C
需求:递归打印文件的多级目录(包括子文件夹和子文件)
分析:多级目录的打印,就是目录的嵌套。在遍历之前,无法知道到底有多少级目录,所以我们依然要使用递归实现
遍历的文件目录如下:
 
 代码演示:
import java.io.File;
/**
 * @author layman
 */
public class Demo02 {
    public static void main(String[] args) {
        File dir  = new File("D:\\movie");
        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(file);
            }
        }
    }
}
运行结果:
目录:D:\movie\Japanese
文件名:D:\movie\Japanese\愤怒的大象.avi
目录:D:\movie\Japanese\电车
文件名:D:\movie\Japanese\电车\葫芦.avi
目录:D:\movie\欧美
文件名:D:\movie\法外狂徒.3gp
 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号