本次lecture的主要内容简述了初步的递归操作,主要包括了线形递归和尾递归。
一、lecture
lecture ppt:https://inst.eecs.berkeley.edu/~cs61a/sp21/assets/slides/06-Recursion_full.pdf
简单的线性回归,我们简单讨论一下如下的例子(同ppt)。可以看到函数的要求是返回1到N的所有数的平方和,这种类型既可以考虑循环操作又可以考虑递归操作,递归操作就是如下所示,“自己调用自己”。
#作为对比我也列出了循环的写法
def sum_squares(N):
sum = 0 #新创建一个变量储存要返回的值
for i in range(N+1): #for i in range(1,N+1)
sum += i ** 2
return sum
#递归写法
def sum_squares(N):
"""
函数的目的是返回N个数的平方和
"""
if N < 1: #注意结束递归的条件,这里课上重点提及
return 0
else:
return sum_squares(N-1) + N ** 2
本次课程还提到一种我以前基本没有见到过的成为尾递归,我认为可以类比于想象为循环的从小往大循环(类比) ,比如上述的简单递归可以写成如下形式:
#tail recursion
def sum_squares(N):
"求从1到N的平方和"
def part_sum(accum,k):
if k <= N:
return part_sum(accum + k ** 2,k + 1)
else:
return accumulating
return part_sum(0,1)
为了更好的理解这种尾递归的方式,我将这个程序输入到python tutor中做进一步的分析。
尾递归演示地址:Online Python Tutor - Composing Programs - Python 3
可以在这个步骤中看到,前面的是建立两个函数的环境,最后sum_squares函数返回的是调用part_sum函数,这里可以理解为简单递归里的sum初始值。然后接着执行part_sum后就可以看到一层一层的计算平方和,具体的执行过程如下:
可以看到这里一共执行了四个part_sum函数和一次sum_squares函数,与简单递归不同的是,这种情况是多次执行嵌套内的函数,而不是最外层函数。
避免无穷递归的方法:
1、数据中肯定会有一个最小的值,比如上例中求1-n的平方和,那么我们可以认为这个1就是这个最小值,也可以认为是停止递归的边界条件;
2、每次递归应该是比前一次简化了问题。(这句话是我自己的“机翻”),简单来说就是每次递归都要使问题简化,以便于趋向于问题的边界最小值;
3、注意递归的执行次数是有限的;
4、(lecture中提到)所有的循环问题都可以用递归问题解决