一、生活中的例子:
场景:问路
递归
问题:天安门怎么走?(等待回答)
A:左拐。/ 接下来怎么走不知道了,你等下,我去问B (A等待B的回答)
B:右拐。/ 接下来怎么走不知道了,你等下,我去问C (B等待C的回答)
C:左拐。/ 接下来怎么走不知道了,你等下,我去问D (C等待D的回答)
D:直行就到了。
* 提问者 → A → B → C → D → C → B → A → 提问者
尾递归
问题:天安门怎么走?给你个小纸条,帮我写在上面(等待回答)
A:写上 “左拐”。/ 接下来把纸条给B (A空闲了)
B:写上 “右拐”。/ 接下来把纸条给C (B空闲了)
C:写上 “左拐”。/ 接下来把纸条给D (C空闲了)
D:写上 “直行就到了”。(把纸条直接给提问者)
* 提问者 → A → B → C → D → 提问者
二、Python代码实例
递归
代码
def foo(x): if x == 1: return x else: return x * foo(x - 1)
执行过程
===> foo(5)
===> 5 * foo(4)
===> 5 * (4 * foo(3))
===> 5 * (4 * (3 * foo(2)))
===> 5 * (4 * (3 * (2 * foo(1))))
===> 5 * (4 * (3 * (2 * 1)))
===> 5 * (4 * (3 * 2))
===> 5 * (4 * 6)
===> 5 * 24
===> 120
尾递归
代码
def foo_iter(num, product): if num == 1: return product return foo_iter(num - 1, num * product)
执行过程
===> foo_iter(5, 1)
===> foo_iter(4, 5)
===> foo_iter(3, 20) ===> foo_iter(2, 60) ===> foo_iter(1, 120) ===> 120
三、总结
1.递归(英语:Recursion),在数学与计算机科学中,是指在函数的定义中使用函数自身的方法。
2.递归函数的优点是定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。
3.尾递归是一种形式,只是用这种形式表达出的概念可以被默写编译器优化,尾递归的特殊形式决定了这种递归代码在执行过程中是可以不需要回溯的(通常递归都是需要回溯的)。
如果编译器针对尾递归形式的递归代码作了这种优化,就可能把原本需要线性复杂度栈内存空间的执行过程用常数复杂度的空间完成。
四、参考链接
https://zh.wikipedia.org/wiki/%E9%80%92%E5%BD%92 ,from 维基百科
- https://www.liaoxuefeng.com/wiki/1016959663602400/1017268131039072 , from 廖雪峰官方网站
- https://www.zhihu.com/question/20761771/answer/20672305,from 知乎