什么是递归
递归是一种重要的程序设计方法。简单的说,若在一个函数、过程或数据结构的定义中又应用了它自身,则这个函数、过程或数据结构称为是递归定义的,简称递归。
什么是栈
栈是一种数据结构…略
栈与递归的关系
使用计算机实现递归,其实是一种栈的应用
实战
递归完成斐波拉契前20项。关键代码加上注释。
斐波拉契数列:1 1 2 3 5 8 13……(第一项和第二项为1,从第三项开始其值是前两项之和)
python代码
# 思路
'''
0.了解斐波那契数学逻辑
1.使用函数递归调用的出栈时的返回值作为斐波那契值
2.使用函数递归调用时的出栈顺序作为斐波那契数列的顺序
3.使用一个li_printed列表保存已打印项,避免重复打印
'''
li_printed = [] # 定义一个列表存打印过的斐波那契第n项
def print_Fib(n):
'''打印斐波那契数列前n项'''
if n == 1: # 本递归函数最终需要的出口之一
if n not in li_printed: # 当n=1时函数递归结束,print_Fib(1)会出栈,此时打印斐波那契第一项的值
li_printed.append(n) # 会打印第一项的值,把第一项添加到已打印列表
print(1, end='\t')
return 1
if n == 0: # 本递归函数最终需要的出口之一
return 0
x = print_Fib(n - 1) + print_Fib(n - 2) # 斐波那契的数学关系,第n项的值等于前两项的值之和
if n not in li_printed: # 判断第n项是否打印过,如果未打印则执行下面的函数进行打印
li_printed.append(n) # 会打印第n项,把n的值传入已打印列表
print(x, end='\t') # 打印第n项的值
return x # 函数返回第n项的值
print_Fib(20)
知识点:
- 递归的定义,以及如何使用递归完成一个任务
- 递归在内存中的入栈和出栈原理
- 列表方法( list.append() )可以在函数内直接使用也能够改变列表的值,不用global声明。其原理是系统从函数内向外寻找list的地址,函数内没有list变量,则最终找到全局变量list,再使用全局变量list的地址进行相应方法。同样不用声明的还有字典等可变数据类型
- 递归的出口。
- 递归中使用return递归。return后面是需要return的东西,层层接收返回,返回即退出
简要解析递归入栈与出栈
Fib代码:
def Fib(n):
'''斐波那契第n项值'''
if n == 1: # 本递归函数最终需要的出口之一
return 1
if n == 0: # 本递归函数最终需要的出口之一
return 0
return Fib(n - 1) + Fib(n - 2) # 函数返回第n项的值
Fib(5)
以Fib(5)为例:
Fib(5)入栈,Fib(4)入栈,Fib(3)入栈,Fib(2)入栈,Fib(1)入栈,Fib(1)出栈,Fib(0)入栈,Fib(0)出栈,Fib(2)出栈,Fib(1)入栈,Fib(1)出栈,Fib(3)出栈,Fib(2)入栈,Fib(1)入栈,Fib(1)出栈,Fib(0)入栈,Fib(0)出栈,Fib(2)出栈,Fib(4)出栈,Fib(3)入栈,Fib(2)入栈,Fib(1)入栈,Fib(1)出栈,Fib(0)入栈,Fib(0)出栈,Fib(1)入栈,Fib(1)出栈,Fib(3)出栈,Fib(5)出栈,函数结束
如果在函数内打印,则打印顺序就是出栈顺序,将上列出栈顺序排列一下:
- Fib(1)出栈,Fib(0)出栈,Fib(2)出栈,Fib(1)出栈,Fib(3)出栈,Fib(1)出栈,Fib(0)出栈,Fib(2)出栈,Fib(4)出栈,Fib(1)出栈,Fib(0)出栈,Fib(1)出栈,Fib(3)出栈,Fib(5)出栈
Fib(0)仅作为函数出口去除掉:
- Fib(1)出栈,Fib(2)出栈,Fib(1)出栈,Fib(3)出栈,Fib(1)出栈,Fib(2)出栈,Fib(4)出栈,Fib(1)出栈,Fib(1)出栈,Fib(3)出栈,Fib(5)出栈
其值分别对应:
- 1,1,1,2,1,1,3,1,1,2,5
在函数内添加打印测试一下:
def Fib(n):
'''斐波那契第n项值'''
if n == 1: # 本递归函数最终需要的出口之一
print(1,end='\t')
return 1
if n == 0: # 本递归函数最终需要的出口之一
return 0
x = Fib(n - 1) + Fib(n - 2)
print(x,end='\t')
return x # 函数返回第n项的值
Fib(5)
结果一致。