什么是递归 递归是一种解决问题的方法,它把一个问题分解为越来越小的子问题,直到问题的规模小到可以被很简单直接解决。通常为了达到分解问题的效果,递归过程中要引入一个调用自身的函数。乍一看,递归算法并没有什么特别的地方,但是,利用递归我们能够写出极为简明的解决问题的方法,而且如果不用递归,这些问题将具有很大的编程难度。
计算数字列表的和 我们先从一个简单的问题开始我们的探究,这个问题不需要递归也可以解决。假如你想对一个数字列表进行求和(例如[1,3,5,7,9]),代码所示的是一个通过迭代函数(for 循环)求和的程序。这个函数用一个变化着的“累加器”变量(theSum)对列表里面所有的数进行累加求和,也就是从 0 开始,依次加上列表中的每个数。
def list_sum(num_list):
the_sum = 0
for i in num_list:
the_sum = the_sum + i
return the_sum
print(list_sum([1,3,5,7,9]))
现在,假设我们不能使用 while 循环或者 for 循环,那么你会如何对数字列表中的数进行求和呢?如果你是个数学家,那么你首先想到的也许是:按照定义,加法是一个有两个参数——两个数字——的函数。为了将数字列表的问题重新定义为对两个参数求和的问题,我们可以利用全括号的表达式来重新表示列表,就像这种形式:(1+(3+(5+(7+9))))。
我们注意到最内层的括号中是(7+9),这是不需要任何循环或者特殊的结构就能解决的。事实上,我们可以用以下一系列简化后的式子来计算最终的加和。那么我们怎样将这个思想转化为 Python 代码呢?首先让我们从 Python 列表的角度来重新叙述这个问题。由于数字列表的和是列表中的第一个元素(numList[0])和剩下所有的元素(numList(1:))之和的和,求和问题可以归纳成以下的式子:listSum(numList)=first(numList)+listSum(rest(numList))
在这个等式中,first 代表列表中的第一个元素,而 rest 代表的是列表中除了第一个元素以外
的其他所有元素。此式很容易在 Python 中用代码表示出来。
def list_sum(num_list):
if len(num_list) == 1:
return num_list[0]
else:
return num_list[0] + list_sum(num_list[1:])
print(list_sum([1,3,5,7,9]))
在这个代码中,有一些关键点需要注意。首先,在第二行中,我们检查这个列表中是否只有一个元素。这个检查非常关键,因为它是函数能结束运行的必要条件。对一个长度为 1 的列表来说,它的和显然只是这个列表中的数,其次,在第五行中,函数调用了自身!这就是我们把后一个计算程序称为“递归”的原因。递归函数就是一种调用自身的函数。
递归三大定律
- 递归算法必须有个基本结束条件
- 递归算法必须改变自己的状态并向基本结束条件演进
- 递归算法必须递归地调用自身
下面我们将以十进制的 769 为例看一个具体的问题。
假设我们有一个字符序列来对应前 10 个数字,形如 convString=“0123456789”。通过在字符串中检索,很容易将小于 10 的整数转换成对应的字符串。例如,如果数字是 9,那么字符串是 convString[9]或"9"。如果我们可以将数字 769 拆成三个单独的数字 7、6 和 9,然后很容易地将它转换成字符串。小于 10 的整数看起来是个不错的基本结束条件。
确定进位数之后整个算法将包含 3 个部分:
- 将原始整数分解为一连串的单个数字。
- 通过在字符序列中检索将单个数字转换成字符串。
- 将这些单个数字的字符串连接起来,形成最终的结果。
用整数的除法将 769 除以 10,我们得到 76 余 9。这给了我们两个好的结果。首先,余数是一个小于进位数的数字,通过检索,它可以直接转换成一个字符
第二,我们得到了一个小于初始数字的新数字"76",它能让我们向着“找到小于进位数的单个数字”的基本结束条件演进。现在我们的任务是再将 76 转换为它的字符串形式。我们将再一次使用除法取余得运算,这样分别得到 7 和 6.最后,我们将问题简化为转换数字 7 为字符串形式,因为它满足基本结束条件“n
def to_str(n, base):
convert_string = "0123456789ABCDEF"
if n < base:
return convert_string[n]# 检测基本结束条件
else:
return to_str(n // base, base) + convert_string[n % base]
#10//3=3,10%3=1
#实现递归调用自身,并且减小问题规模print(to_str(17, 16))
请注意,在第 3 行我们检查进位数 base,当 n 小于 base 时我们才会进行转换。当我们检测到基本结束条件时,我们会停止递归过程并且仅仅从 convertString 序列中返回字符串。在第 6 行里,我们在满足递归第二、三条定律的基础上,通过运用除法,做到了递归算法调用自身和减小问题规模这两点。
在第 6 行先使用递归调用to_str(n // base, base),然后添加了字符串表示的余数convert_string[n % base]。如果我们把这两个顺序调换,先返回 convertString 的查找
结果再返回 toStr 调用,生成的字符串将会反向!但通过递归调用返回结果后再进行连接操作,结果是正确的。
栈帧:实现递归 如果不是按上文“toStr()”那样通过递归调用将所得的单个字符连在一起输出得到结果,而是通过修改算法,以类似于递归执行时的先后顺序,把这些字符压入一个栈中来得出结果,会是如何呢?修改后的代码如下所示:
# 使用栈的方法递归调用
class Stack:
def __init__(self):
self.item=[]def isEmpty(self):
return self.item==[]def push(self,item):
self.item.append(item)def pop(self):
return self.item.pop()r_stack = Stack()
def to_str(n, base):
convert_string = "0123456789ABCDEF"
while n > 0:
if n < base:
r_stack.push(convert_string[n])
else:
r_stack.push(convert_string[n % base])
n = n // base
res = ""
while not r_stack.isEmpty():
res = res + str(r_stack.pop())
return res
print(to_str(17, 16))
【python数据结构|python数据结构——递归recursion】这个例子能够是我们了解 Python 是如何执行递归函数的调用的:
在 Python 中,当一个函数被调用时,系统会分配一个栈帧去处理函数中的那些局部变量。当执行完函数,并得到了一个返回值时,这个值会被留在栈顶等待被调用的函数来处理。
文章图片
图示递归
#图示递归,用海龟做一个螺线
import turtle
myTurtle = turtle.Turtle()#创建一只海龟
myWin = turtle.Screen()#创建一个作图的窗口
def drawSpiral(myTurtle, lineLen):#drawSpiral函数的基本结束条件是linLen减小到0
if lineLen > 0:
myTurtle.forward(lineLen)#使海龟前进linLen
myTurtle.right(90)#使海龟右转90度
drawSpiral(myTurtle,lineLen-5)#出现递归drawSpiral(myTurtle,100)myWin.exitonclick()#使海龟待机,单击窗口才会清空
#画分形树
import turtle
def tree(branchLen,t):
if branchLen > 5:
t.forward(branchLen)
t.right(20)
tree(branchLen-15,t)
t.left(40)
tree(branchLen-15,t)
t.right(20)
t.backward(branchLen)
def main():
t = turtle.Turtle()
myWin = turtle.Screen()
t.left(90)
t.up()
t.backward(100)
t.down()
t.color("green")
tree(75,t)
myWin.exitonclick()main()
推荐阅读
- Python中input()和raw_input()函数之间的区别
- Python与机器学习|pandas中如何提取DataFrame的某些列
- 如何使用Python生成罗马风格的马赛克(代码实现)
- 总结十个Python 字典用法的使用技巧
- Go和Python编程语言之间有什么区别()
- Python(使用Tkinter的年龄计算器)
- oeasy教您玩转python - 002 - # 你好世界 - 各位同学除夕快乐,除旧布新之时预祝能玩转python
- oeasy教您玩转python - 003 - #- 继续运行
- 使用Python进行数据分析和可视化|S2