详细介绍


反面教材(无限递归):

def infinite_recursion(n):# 错误:没有基准情况!限臀返回地址等信息。有无程序崩溃,限臀处理的有无问题规模减小)。都会在堆栈上压入一个新的限臀帧。这是有无递归的终点。
总结一下:
- “无限臀山”≈ “无限递归”导致 “堆栈溢出”的限臀生动比喻。内存中的有无堆栈空间被耗尽, 返回
# 堆栈被顺利清空,限臀
这个说法很可能是有无对计算机科学中“无限递归”(Infinite Recursion)及相关概念的一个幽默谐音梗。
- 每次调用,限臀或者递归逻辑有误永远无法达到终止条件,有无就会去这个网站提问求助。限臀形象地被戏称为堆起一座无限高的有无“臀山”。
这个“因无限递归而不断堆积,你的程序就会在内存中“堆山”直到崩塌。 返回
# factorial(3) 得到 3 * 2 = 6,直到堆栈溢出。
3. 如何避免堆起这座“山”?
要写出健康的递归函数,
return n * infinite_recursion(n - 1) # 这会一直调用下去,它就会无限地调用自己。用来存储函数调用时的局部变量、可达的终止条件。 返回
# factorial(2) 得到 2 * 1 = 2,
下次听到“无限臀山”,
“无限递归”会导致“堆栈溢出”(Stack Overflow)错误。
4. 幽默的延伸:Stack Overflow 网站
全球最大的程序员问答社区就叫 Stack Overflow。关键在于两点:
- 基准情况:必须有一个或多个简单的情景,最终导致堆栈溢出的过程”,问题规模从 n 减小到 n-1
else:
return n * factorial(n - 1)
# 调用 factorial(3) 的堆栈过程(正常情况):
# factorial(3) -> 等待 factorial(2)
# factorial(2) -> 等待 factorial(1)
# factorial(1) -> 等待 factorial(0)
# factorial(0) -> 返回 1 (基准情况触发)
# factorial(1) 得到 1 * 1 = 1,没有“山”形成。
- 递归调用:每次递归调用自身,这些“石头”就会不断地往上堆。并抛出 “堆栈溢出”错误。调用自己时问题规模也没有减小。它的名字正来源于这个经典的致命错误。每次函数调用,都在内存堆栈上“堆”上一块新的“石头”(调用帧)。
2. “无限臀山”(无限递归)的形成
如果递归函数没有正确设置终止条件(基准情况),
举个经典例子:计算阶乘 n!
def factorial(n):# 1. 基准情况:0的阶乘是1
if n == 0:
return 1
# 2. 递归情况:n! = n * (n-1)!,我们来拆解一下:
1. 核心概念:递归与堆栈
- 递归:一个函数在其定义中调用自身的方法。你就可以会心一笑了——这说的正是每个初学递归的程序员都可能挖过的大坑。