递归
来源:互联网 发布:狗爹怎么解析域名 编辑:程序博客网 时间:2024/06/03 19:20
开始讨论递归前需要知道递归的两个特性:存在限制条件,当符合这个条件时,递归便不再继续;每次递归调用后越来越接近这个限制条件。
当一个问题相当复杂,难以用迭代形式实现时,此时递归的简洁性便可以补偿它所带来运行时的开销。
https://www.zhihu.com/question/31412436,转自知乎,如侵权联系我
1、在用递归的时候,当成一个黑盒子,不要老是想着递归这着方法,而是只是把递归函数当成一个普通的调用函数,对这个函数,你需要知道他的输入与输出。
2、将递归一步步展开可以理解递归。
3、可以类比数学归纳法…
第一步:先检查退出条件是否正确,这相当于归纳法中的初值f(0)。
第二步:假设在递归函数中被调用的函数自身返回成功,看递归函数是否正确,这相当于归纳法中从 f (k-1)到f(k)的过程。
这个方法不但有助于理解分析递归函数,也有助于编写递归函数。比如最简单的n的阶乘的递归实现,代码如下。
function factorial (n) {
if (n === 1) {
return n;
} else {
return n * factorial(n-1);
}
}
你在写这个函数的时候,把函数定义部分代码蒙起来,主要看这部分代码
if (n === 1) { // 如果求1的阶乘,那么就直接返回
return n;
} else { // n! = n * (n-1)! 这个数学等式
return n * factorial(n-1);
}
那这样看代码,你懂了吗?
如果你觉得还不懂的话,且听我下面说完。
不说性能上面的影响,递归的使用能让你的代码变得简单清晰,逻辑变得易懂,就比如下面这段代码,用非递归的方式实现阶乘。
function factorial (n) {
var result = 1;
for (var i = n; i > 0; i--) {
result *= i;
}
return result;
}
这个函数与前面的递归函数求值是一样的,但是在函数逻辑上面差别非常大。
在递归函数里面,运用了一部分的数学逻辑在里面,能清晰看见数学等式,而非递归实现里面数学逻辑其实是隐藏起来的,是编码人员在知道数学逻辑的情况下实现,而没有体现在代码层面上。这样在数学逻辑变动的时候,维护起来是不太好的。
如果递归不能让你的代码变得清晰,你自己看代码也会迷惑,那就不要生硬得用递归了。
递归隐式地使用了一个数据结构来存放调用栈上的数据。这意味着应该有一个等价的显示栈来避免使用递归解决方案。例如二叉树的前序遍历,递归调用用于在隐式的栈上存储右子树的地址,因此可以在左子树遍历完成后,可以继续遍历右子树,因此从一个递归的调用中返回,实际上是从隐式的栈上弹出右子树节点的地址,这样就可以继续的遍历。
- 递归
- 递归
- 递归
- 递归
- 递归
- 递归
- 递归
- 递归
- 递归
- 递归
- 递归
- 递归
- 递归
- 递归
- 递归
- 递归
- 递归
- 递归
- Android帧动画创建方法
- HTML5与CSS3学习心得
- HDU5616 背包 天平平衡问题
- ScrollView嵌套View后,让ScrollView置顶的方法
- 哈理工OJ 1997 又是一个神奇的布尔矩阵(判断)
- 递归
- NBUT 1670 字符串(strstr函数的处理)
- git pull 代码时报错
- servlet的执行过程
- POJ 3160 Father Christmas flymouse(强连通分量+spfa最长路)
- Unity3D各平台Application.xxxPath的路径
- SDUT(3377)数据结构实验之查找五:平方之哈希表
- UNIX编程初遇问题ourhdr.h文件
- 生产者消费者Java实现