在我看来,递归就相似俄罗斯套娃,一次次重复去执行相同的操做,最后得出结果的过程。算法
不少递归的操做均可以使用循环来替代。递归并无带来算法性能上的优点,甚至更差,可是使用递归可能让你的程序更易理解。因此理解递归这种概念很重要。编程
因为递归函数调用本身,很容易致使无线循环。好比,你须要一个倒数的函数:bash
def countdown(i):
print(i)
countdown(i - 1)
countdown(3)
复制代码
若是运行上述代码,这个函数就会不停的运行。函数
编写递归函数式,必须告诉它什么时候中止递归,性能
每一个递归函数都有两部分:基线条件(base case)和递归条件(recursive case)。递归条件指的是函数调用本身,而基线条件则 指的是函数再也不调用本身,从而避免造成无限循环。优化
好了,咱们尝试为上面的代码增长基线条件:ui
def countdown(i):
print(i)
if i <= 0: # 基线条件
return
else: # 递归条件
countdown(i - 1)
countdown(3)
# 3 2 1 0 程序中止
复制代码
调用栈不只对于编程来讲很重要,使用递归是也必须裂解这个概念。计算机在内部使用被称为调用栈的栈。spa
咱们简单看一个例子:code
# 忽略 print 这个函数带来的影响
# 开始执行函数 greet ,此时内存中开辟一块空间 greet 进入栈中
def greet(name):
# 在 greet 的内存中,添加变量name
print "hello, " + name + "!"
# 开始执行 greet2 ,此时内存中开辟空间 greet2,greet2 入栈
# greet <-- greet2 相似这种链式结构
greet2(name)
# greet2 执行完毕,出栈
# greet
print "getting ready to say bye..."
# 开始执行bye ,此时内存中开辟空间 bye,bye 入栈
# greet <-- bye
bye()
# bye 执行完毕,出栈
# greet
# 最后greet执行完毕,出栈
复制代码
栈的执行逻辑就是:先进后出原则。递归
递归调用中,存储详尽的信息可能占用大量的内存。这回付出很大的代价。若是占用太高,你须要使用循环去代替递归,或者使用尾递归优化,前提是你的语言支持尾递归优化。