java之递归【通俗易懂】

概念

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

递归的分类:

  1. 直接递归:方法直接调用自己。比如方法A调用方法A
  2. 间接递归:方法间接调用自己。比如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
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值