1.什么是递归?
在函数或子过程的内部,直接或者间接地调用自己的算法。
我自己通俗的理解是:要解决当前这个问题,就要先解决另一个问题,顾名思义,先递后归。
例如,做一碗面条,就要先完成放面入锅的操作,而这个操作的前提又是水烧滚,烧水之前还要先放油。所以,第一个操作就是放油,然后烧水,然后放面,最后出锅。
一句话就是:由结论入手,摸索到前提,最后从前提出发。
就像数学里的证明题,也像一些博主说的数学归纳法,高中做数列的时候也是这个道理。典型的递归有:汉诺塔问题,阶乘,斐波那契数列等。
2.为什么要用递归?
众所周知,递归在空间性能方面是非常糟糕的。那我们为什么还要用递归?有两个原因:
a.首先对于无限循环,用for肯定是无法实现的;而且递归也适用于不定长字段;
b.递归的语句简洁,虽然难理解一点。
3.如何设计递归算法?
首先,要确定两件事:
1.确定递归公式
2.确定边界(终了)条件
接下来,我们来剖析递归的结构:
void func( mode)
{
if(endCondition)
//结束状态(类似于数列的首项,或者说数学归纳法的前面几项)
{
constExpression //基本项
}
else
{
accumrateExpreesion //归纳项(类似于数列的通项)
mode=expression //步进表达式(数列里第n项和第n-1项的关系)
func(mode) //调用本身,递归
}
}
// 递归计算阶乘
int factorial(n){
if(n == 1) {//首项0! = 1;
return 1;
}
return n * factorial(n-1); //和第n项的关系(步进表达式)
}
4.哪些情况适合用递归?
1.可以通过递归调用来缩小问题规模,且新问题与原问题有着相同的形式。 2.存在一种简单情境,可以使递归在简单情境下退出。
5.总结:
递归的基本思想是把规模大的问题转化为规模小的相似的子问题来解决。在函数实现时,因为解决大问题的方法和解决小问题的方法往往是同一个方法,所以就产生了函数调用它自身的情况。另外这个解决问题的函数必须有明显的结束条件,这样就不会产生无限递归的情况了。