递归(Recursion),又译为递回,是指在函数的定义中使用函数自身的方法。
递归只是让解决方案更清晰,并没有性能上的优势。实际上,在有些情况下,使用循环的性能更好。如果使用循环,程序的性能可能更高;如果使用递归,程序可能更容易理解。
>递归函数的组成:
1. 基线条件(base case)即函数不再调用自己,从而避免无限循环;
2. 递归条件(recursive case)即自己调用自己。
递归条件一定是向基线条件靠拢的,否则,只能无限递归下去。
在计算结科学中是一种通过重复将问题分解为同类的子问题而解决问题的方法。
计算机科学家尼克劳斯·维尔特如此描述递归:递归的强大之处在于它允许用户用有限的语句描述无限的对象。因此,在计算机科学中,递归可以被用来描述无限的运算,尽管描述运算的程序是有限的。
堆栈(stack)
又称为栈或堆叠,是一种抽象数据类型,只允许在有序的线性数据集合的一端(称为堆栈顶端,英语:top)进行加入数据(英语:push)和移除数据(英语:pop)的运算。因而按照后进先出(LIFO,Last In First Out)的原理运作。
堆栈常用一维数组或者链表来实现。堆栈常用两种基本操作,推入(压栈,push)和弹出(弹栈,pop):
- 推入:将数据放入堆栈的顶端,堆栈顶端移动到新放入的数据;
- 弹出:将堆栈顶端数据移除,堆栈顶端移动到移除后的下一个数据。
堆栈的特点:
1. 先入后出,后入先出;
2. 除头尾节点之外,每个元素有一个前驱,一个后继。
递归程序
简单的一个Python写法的递归程序示例:
def RecursiveTest():
RecursiveTest() #自己调用自己
以上的程序是一个最简单的递归,但因为无限调用自己而不会停下,就会因为**栈空间溢出**而导致程序产生异常而强制停止,而Python会因为自身设置的保护措施,而不断的抛出异常。
简单写一个不带任何条件的递归函数:
def countdown(i):
print(i)
countdown(i-1)
countdown(3)
如果运行上面这个函数,我们会发现它会不停的运行。
所以编写递归函数时候,你必须要告诉它什么时候停下来(停止递归);加上基线条件的代码就可以避免无限循环,示例如下:
def countdown(i):
if i <= 0: #基线条件
return
else: #递归条件
countdown(i-1)
countdown(3)
#3 2 1 0 程序停止
#开始执行函数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执行完毕,出栈