一.介绍
程序调用自身的编程技巧称为递归( recursion)。递归做为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合。一般来说,递归需要有边界条件、递归前进段和递归返回段。当边界条件不满足时,递归前进;当边界条件满足时,递归返回。
二.知识点介绍
1、递归的概念
2、递归的注意事项
3、算法案例
三.上课视频对应说明文档
1、递归的概念
递归就是“在一个方法内可以再次调用自身”,如下,method方法又调用了method方法。
public class Demo {
public static void main(String[] args) {
method();
}
private static void method() {
System.out.println("调用method()");
method();
}
}
上面的程序运行后,控制台会一直打印:调用method();当然,运行不久就会看到JVM抛出“堆栈溢出异常”——它类似于“无限循环”,但它比循环更消耗内存;
递归方法开始调用后,在内存中会存在多个method方法,每个method方法均会等待它调用的method方法执行完毕,自己才会执行完毕。
/*
* 递归: 方法自己调用自己 .
* public void fun(){
* fun();
* }
*/
public class Demo {
public static void main(String[] args) {
story();
}
static int count = 0;
public static void story() {
count++;
System.out.println("从前有座山");
System.out.println("山里有个庙");
System.out.println("庙里有个老和尚给小和尚讲故事");
System.out.println("讲什么呢? ");
System.out.println(count);
story();
}
}
2、递归的注意事项
递归调用必须要在某个条件下结束,否则就是死递归。
递归调用的层次不能太多,否则会堆栈溢出。
构造方法不能递归调用
3、算法案例
(1)有些问题可以使用“循环”,也可以使用“递归”解决:求5的阶乘:表示为:1 * 2 * 3 * 4 * 5
使用循环:
public static void main(String[] args) {
int max = 5;
int num = 1;
int result = 1;
while(num <= max){
result *= num;
num++;
}
System.out.println("result = " + result);
}
使用递归:
算法分析:
5! = 5 * 4!;
4! = 4 * 3!;
3! = 3 * 2!;
2!= 2 * 1!;
1! = 1;
先求1的阶乘,再求2的阶乘......求5的阶乘;
代码:
public static void main(String[] args) {
System.out.println("递归结果:" + jieCheng(5));
}
public static int jieCheng(int num){
if(num == 1){
return 1;
}
return num * jieCheng(num - 1);
}
4、递归两种方法
递归分为两种,直接递归和间接递归。
直接递归称为方法自身调用自己。间接递归可以A方法调用B方法,B方法调用C方法,C方法调用A方法。
(1)递归的代码演示,计算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);
}
}
(2)代码执行流程图解
注意:递归一定要有条件限定,保证递归能够停止下来,否则会发生栈内存溢出。
在递归中虽然有限定条件,但是递归次数不能太多。否则也会发生栈内存溢出。
5、递归打印所有子目录中的文件路径
编写一个方法用来打印指定目录中的文件路径,并进行方法的调用
要求:若指定的目录有子目录,那么把子目录中的文件路径也打印出来
步骤:
(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);
}
}
}
}