In order to understand recursion, one must first understand recursion.
To Iterate is Human, to Recurse, Divine.
递归的定义
子程序或者函数直接或者间接地调用自身。 递归是一种描述问题和解决问题的基本方法,相比(循环)之下递归写出的代码可读性更好,不过性能上并没有优势。此外,很多算法的实现都离不开递归。
递去归来,递是描述问题,归时解决问题。
//例如A()函数内部调用了自己,叫做
//直接递归调用
function A(){
A();
}
//间接递归调用
function B(){
C();
}
function C(){
B();
}
//尾递归
function A(){
return A()
//作为return返回时调用,称为尾递归
}
复制代码
递归的基本结构:
- 递归项&递归关系 (Recursive Case) 描述大问题如何分解为小问题,也称为递归体
- 递归边界条件(Base Case) 停止递归的条件,也称为递归出口
// 伪代码
function recurtion(sth){
if(stopRecurtion === true){ //base case
return
}else{ //recurtion case
sth=expression //与子问题的递归关系
recurtion(sth) //调用自身
}
}
recurtion(sth)
复制代码
递归调用栈 The Call Stack
也称为递归工作栈,层层向下递归,返回次序正好(与调用次序)相反
即递归中的每个子函数的调用是放入一个调用栈来执行,后进先出,所以递归到最深的子问题时开始逐层向上返回。
递归的一些简单应用
- 阶乘
- 递归算法
- 非递归算法
- 斐波那契竖列求解
- 递归算法
- 非递归算法
- 回文串
- 递归算法
- 非递归算法
小结
应用递归解决的思路:
- 找到最小子问题
- 找到递归关系,即如何从顶层到达下一层的条件(关系)
- 写出最小子问题的解决过程,在恰当的时候调用自己(实现递归关系)
- 递的分析可以将问题关系描述清楚,归的分析也是难点,是解决问题的关键
- 理解递归的执行栈可以帮助理清楚归的过程
参考