-
递归:指在当前方法内调用自己的这种现象。
-
递归的分类:
-
递归分为两种,直接递归和间接递归。
-
直接递归称为方法自身调用自己。
-
间接递归可以A方法调用B方法,B方法调用C方法,C方法调用A方法。
-
-
注意事项:
-
递归一定要有条件限定,保证递归能够停止下来,否则会发生栈内存溢出。
-
在递归中虽然有限定条件,但是递归次数不能太多。否则也会发生栈内存溢出。
-
构造方法,禁止递归
-
没有停止条件,导致栈内存溢出。
package com.itheima.demo02.Recursion;
public class Demo01Recurison {
public static void main(String[] args) {
// a();
b(1);
}
/*
构造方法,禁止递归
编译报错:构造方法是创建对象使用的,一直递归会导致内存中有无数多个对象,直接编译报错
*/
public Demo01Recurison() {
//Demo01Recurison();
}
/*
在递归中虽然有限定条件,但是递归次数不能太多。否则也会发生栈内存溢出。
11157
Exception in thread "main" java.lang.StackOverflowError
*/
private static void b(int i) {
System.out.println(i);
if(i==200){
return; //结束方法
}
b(++i);
}
/*
递归一定要有条件限定,保证递归能够停止下来,否则会发生栈内存溢出。
Exception in thread "main" java.lang.StackOverflowError
*/
private static void a() { //停不下来
System.out.println("a方法!");
a();
}
}
执行结果:
1
2
3
4
5
6
7
8
9
练习_使用递归计算1-n之间的和
/*
定义一个方法,使用递归计算1-n之间的和
1+2+3+...+n
n+(n-1)+(n-2)+...+1
已知:
最大值:n
最小值:1
使用递归必须明确:
1.递归的结束条件
获取到1的时候结束
2.递归的目的
获取下一个被加的数字(n-1)
*/
package com.itheima.demo02.Recursion;
public class Demo02Recurison {
public static void main(String[] args) {
int s = sum(6);
System.out.println(s);
}
public static int sum(int n){
//获取到1的时候结束
if(n==1){
return 1;
}
//获取下一个被加的数字(n-1)
return n + sum(n-1);
}
}
执行结果:
21
Process finished with exit code 0
递归累加求和
计算1 ~ n的和
分析:num的累和 = num + (num-1)的累和,所以可以把累和的操作定义成一个方法,递归调用。
/*
定义方法使用递归计算阶乘
5的阶乘: 5! = 5*(5-1)*(5-2)*(5-3)*(5-4)=5*4*3*2*1
递归结束的条件
获取到1的时候结束
递归的目的
获取下一个被乘的数字(n-1)
方法的参数发生变化
5,4,3,2,1
*/
实现代码:
package com.itheima.demo02.Recursion;
/*
练习:
使用递归计算阶乘
n的阶乘:n! = n * (n-1) *...* 3 * 2 * 1
*/
public class Demo03Recurison {
public static void main(String[] args) {
int jiecheng = jc(5);
System.out.println(jiecheng);
}
public static int jc(int n){
//获取到1的时候结束
if(n==1){
return 1;
}
//获取下一个被乘的数字(n-1)
return n * jc(n-1);
}
}
执行结果:
120
Process finished with exit code 0
练习_递归打印多级目录
package com.itheima.demo02.Recursion;
import java.io.File;
public class Demo04Recurison {
public static void main(String[] args) {
File file = new File("08_FileAndRecursion\\111");
getAllFile(file);
}
/*
定义一个方法,参数传递File类型的目录
方法中对目录进行遍历
*/
public static void getAllFile(File dir){
System.out.println(dir);//打印被遍历的目录名称
File[] files = dir.listFiles();
for (File f : files) {
//对遍历得到的File对象f进行判断,判断是否是文件夹
if(f.isDirectory()){
//f是一个文件夹,则继续遍历这个文件夹
//我们发现getAllFile方法就是传递文件夹,遍历文件夹的方法
//所以直接调用getAllFile方法即可:递归(自己调用自己)
getAllFile(f);
}else{
//f是一个文件,直接打印即可
System.out.println(f); //文件则打印,文件夹则继续进入
}
}
}
}
遇到是文件夹则遍历其下文件/文件夹,遇到文件则打印出它的名字。
执行结果:
08_FileAndRecursion\111
08_FileAndRecursion\111\222
08_FileAndRecursion\111\222\333
08_FileAndRecursion\111\222\333\444
08_FileAndRecursion\111\222\bbb
08_FileAndRecursion\111\222\bbb\fuck.txt
Process finished with exit code 0
文件搜索
搜索目录中的.txt
文件。
分析:
-
目录搜索,无法判断多少级目录,所以使用递归,遍历所有目录。
-
遍历目录时,获取的子文件,通过文件名称,判断是否符合条件。
代码实现:
package com.itheima.demo02.Recursion;
import java.io.File;
public class Demo05Recurison {
public static void main(String[] args) {
File file = new File("08_FileAndRecursion/111");
getAllFile(file);
}
/*
定义一个方法,参数传递File类型的目录
方法中对目录进行遍历
*/
public static void getAllFile(File dir){
//System.out.println(dir);//打印被遍历的目录名称
File[] files = dir.listFiles();
for (File f : files) {
//对遍历得到的File对象f进行判断,判断是否是文件夹
if(f.isDirectory()){
//f是一个文件夹,则继续遍历这个文件夹
//我们发现getAllFile方法就是传递文件夹,遍历文件夹的方法
//所以直接调用getAllFile方法即可:递归(自己调用自己)
getAllFile(f);
}else{
//f是一个文件,直接打印即可
if(f.getName().toLowerCase().endsWith(".txt")){ //打印txt结尾的文件
System.out.println(f);
}
}
}
}
}
递归,遇到txt结尾的则打印。
打印结果:
08_FileAndRecursion\111\222\bbb\fuck.txt
Process finished with exit code 0