递归,就是在运行的过程中调用自己。
递归的介绍
我们先来看这样一段话,大家小时候一定听过这个故事吧,“从前有座山,山里有座庙,庙里有个老和尚和小和尚,老和尚给小和尚讲故事:从前有座山,山里有座庙,庙里有个老和尚和小和尚,老和尚给小和尚讲故事:… …”当然,这是一个“无穷无尽”的故事,并没有结束的条件,可以一直讲下去。
以上内容用代码表示如下:
public class TestDemo1 {
public static String tellStory(String str){
System.out.println(str);
return tellStory(str);
}
public static void main(String[]args){
tellStory("从前有座山,山里有座庙,庙里有个老和尚和小和尚,老和尚给小和尚讲故事:");
}
}
运行结果如下:
当然,前面提到过,这是一个“无穷无尽”故事,并没有终止条件,所以会一直讲下去,严格意义上这并不是递归,因为没有终止条件,会进入一个死循环,而我们的递归执行时产生的内存等是存放在栈内存上的,栈内存的空间也是有限的,如此无限下去会导致栈溢出,如下所示:
这里就需要我们来了解一下递归的基本条件了:
1. 递归要有终止条件;
2. 递归的前进段(也称递归的入口);
3. 递归的返回段(也称递归的出口)。
当递归的终止条件不满足时,递归前进;满足时,递归返回。
下面这张图可以抽象的解释递归的过程:
下面附上一个链接,来详细了解递归。(强烈建议点击此链接,加深对递归的理解!)
点击此处详细了解递归:https://blog.youkuaiyun.com/wener521/article/details/89331560
这就是递归!你明白了吗?
在一部很经典的电影《盗梦空间》里,电影里面总共有四层梦境,每次都是通过做梦的方式进入下一层梦境,而要想从第四层梦境(最高层梦境)回来的话,就需要上一层梦境的人给你一个kick的信号或者自己从高空坠落等才会回到上一层梦境,然后再由上上一层梦境的人给你一个kick的信号…依次类推,直到回到现实生活中来。这就很好的反映出了递归的思想:
- 子问题须与原始问题为同样的事(通过做梦进入下一层梦境);
- 且更为简单不能无限制地调用本身,须有个出口(由上一层的人给kick信号),化简为非递归状况处理。
或许你还不太明白的话,那么我再来举几个栗子。你一定见过这几个场景:在两个互相平行的两个相向而放的镜子里面可以产生无限多个镜像,一直延伸下去…;你正在看某个主播的直播,而主播也打开了他自己的直播间,在他的电脑屏幕上就会出现他打开的他直播间的画面,而在打开后的画面里又是他打开的自己直播间的画面…这些效应称为德罗斯特效应,是递归的一种视觉形式,这些都是抽象出来的递归,只不过没有终止的条件而形成了死循环。
递归思想的应用
递归算法一般用于解决三类问题:
- 数据的定义是按递归定义的。(Fibonacci函数)
- 问题解法按递归算法实现。
这类问题虽则本身没有明显的递归结构,但用递归求解比迭代求解更简单,如Hanoi问题。 - 数据的结构形式是按递归定义的。
如二叉树、广义表等,由于结构本身固有的递归特性,则它们的操作可递归地描述。
这里附上一个例子,用递归的思想求n的阶乘:
import java.util.Scanner;
public class TestDemo1 {
public static int factor(int n){
if (n == 1) {
return 1;
}
return n * factor(n-1);
}
public static void main(String[]args){
System.out.println("请输入一个数:");
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
System.out.print(n+"的阶乘为:");
System.out.println(factor(n));
}
}
结果如下:
递归的缺点:
递归算法解题相对常用的算法如普通循环等,运行效率较低。因此,应该尽量避免使用递归,除非没有更好的算法或者某种特定情况,递归更为适合的时候。(递归的次数过多容易导致栈溢出)
以上就是我个人对递归思想的理解和认识,如有不足欢迎指出。