递归算法
递归的基本思想是 “自己调用自己” 。
- 递归的基本思想:“自己调用自己”,一个使用递归技术的方法将会直接或间接的调用自己。
- 利用递归可以用简单程序解决一些复杂问题。比如:斐波那契数列的计算、汉诺塔、快排等。
- 递归结构包括两部分:
- 定义递归头。PS:如果没有递归头,将陷入死循环,也就是定义递归的结束条件。
- 递归体。PS:什么时候需要调用自身方法。
递归缺陷:
递归调用会占用大量的系统堆栈,内存耗用多,在递归调用层次多时速度要比循环慢得多,所以使用递归时需慎重。
递归原理分析图
使用递归计算 5! 阶乘

代码示例:简单测试:自己调用自己的方法
- 一个方法里可以去调用其他方法
2.自己调用自时,会一直调用,直到占满系统资源抛出异常。
// 测试递归算法
public class TestRecursion01 {
public static void main(String[] args) {
a(3);
}
static void a(int c){
System.out.println("a");
// 一个方法里可以去调用其他方法
b();
// 自己调用自己:会一直调用,直到占满系统资源抛出异常。
a(3);
}
static void b(){
System.out.println("b");
}
}
代码示例:使用递归计算 n!(对比下方循环效率)
- printf() 输出函数作用:定义一些变量,用来格式化输出。
- %n 作用是输出时实现换行。%n是一种格式字符串,只能用到printf()的参数里。
- %n 是转义字符,可以用于一切字符串。
// 使用递归计算 n!(对比循环效率)
public class TestRecursion {
public static void main(String[] args) {
// 记录 开始 调用方法进行计算的时刻
long d1 = System.currentTimeMillis();
/**
* printf() 输出函数作用:定义一些变量,用来格式化输出。
* %n 作用是输出时实现换行。%n是一种格式字符串,只能用到printf()的参数里。
* %n 是转义字符,可以用于一切字符串。
* */
System.out.printf("%d阶乘的结果是:%s%n",10,factorial(10));
// 记录 结束 调用方法进行计算的时刻
long d2 = System.currentTimeMillis();
System.out.printf("递归消耗时间是:%s ms%n",d2 - d1); // 耗时: ms
}
// 求阶乘的方法
static long factorial(int n){
if (n == 1) {// 递归头
return 1;
}else{ // 递归体:factorial(n - 1) 在方法内反复调用自己,直到 n == 1
return n * factorial(n - 1); // n! = n * (n - 1)!
}
// 1*2*3*4*…*9*10
}
}

注意点
- 任何能用递归解决的问题也能使用迭代解决。
- 当递归方法可以更加自然地反映问题,并且易于理解和调试,并不强调效率问题时,可以采用递归。
- 在要求搞性能的情况下尽量避免使用递归,递归调用既花时间又耗内存。
代码示例:使用循环计算 n!(对比递归效率)
// 使用循环求 n! (对比递归效率)
public class TestRecursion02 {
public static void main(String[] args) {
// 记录 开始 调用方法进行计算的时刻
long d3 = System.currentTimeMillis();
int a = 10;
int result = 1;
while (a > 1){
result *= a * (a-1);
a -= 2;
}
// 记录 结束 调用方法进行计算的时刻
long d4 = System.currentTimeMillis();
System.out.println("10! 阶乘计算结果为:" + result);
System.out.printf("计算消耗时间为:%s ms%n",d4 - d3);
}
}

至此,递归算法知识点以及相关效率对比测试到此结束。