递归调用后的代码递归
Posted
技术标签:
【中文标题】递归调用后的代码递归【英文标题】:Recursion with code after the recursive call 【发布时间】:2018-08-13 17:46:40 【问题描述】:我试图了解递归是如何工作的,但还有一件事我不太明白:当递归函数本身内的递归调用之后有代码时,递归函数是如何工作的.请参阅下面的示例伪代码以帮助了解我的意思。 我的确切问题是递归调用之后的代码将以什么顺序(意味着何时)执行。 机器会注意递归调用,在调用之后执行剩余的代码位(打印“完成”),然后返回并实际执行整个递归调用,或者机器将在到达该行时立即执行递归调用,并且仅在该递归底部之后执行最后一段代码(打印“完成”) out? 什么时候“完成”会被打印多少次?
void recurse()
print "hello world";
for i = 0 up to 2
recurse();
print "done";
【问题讨论】:
当有递归调用时,编译器等不会对代码执行顺序的正常规则做出任何异常。事情的运行顺序与recurse()
完全是其他函数一样。
那么这意味着什么时候和多少次“完成”将被打印?请帮助我理解这一点!我是递归新手!
由于本例中的递归是无限的,因此“完成”never 被打印出来。 (可能不是你想要的。)
@usercow 您是否尝试过使用任何语言?您的函数没有终止条件,这意味着它永远不会停止。对recurse()
的每次调用都会再调用两次,因此它打印"hello world"
的次数将呈指数增长,理论上是无限的。实际上,它最终会在"done"
出现之前耗尽堆栈空间并崩溃。
【参考方案1】:
递归调用在它下面的任何代码之前运行。一旦它返回,它将返回并完成其余的代码。那么会发生什么
"hello world"
i = 0
"hello world"
i = 0
"hello world"
...
永远。因为您没有将i
的值传递给下一个递归函数,所以您的代码将永远运行,每次都以i=0
重新启动。
假设您确实将i
正确传递给了递归函数:
void recurse(i)
// is i still < 2?
if (i < 2)
print "hello world";
recurse(i+1);
print "done";
recurse(0);
在这种情况下,你会得到:
i = 0
"hello world"
i = 1
"hello world"
i = 2
"done"
"done"
【讨论】:
【参考方案2】:可视化递归的一个好方法是使用堆栈的深度/高度。您可能知道,每当调用一个新函数时,它都会像煎饼一样被推入堆栈,将深度/高度增加 1。如果您对其进行编码并打印带有缩进的“开始”和“结束”注释以可视化深度,应该很容易看出什么时候执行的。如果不清楚,时间在 Y 轴上(上面打印的内容在下面的内容之前执行),递归深度在 X 轴上。
这是 Python 中的代码:
def recurse(depth=0):
if depth < 4:
print(" " * depth + f"starting at depth depth")
for _ in range(2):
recurse(depth + 1)
print(" " * depth + f"ending at depth depth")
recurse()
输出:
starting at depth 0
starting at depth 1
starting at depth 2
starting at depth 3
ending at depth 3
starting at depth 3
ending at depth 3
ending at depth 2
starting at depth 2
starting at depth 3
ending at depth 3
starting at depth 3
ending at depth 3
ending at depth 2
ending at depth 1
starting at depth 1
starting at depth 2
starting at depth 3
ending at depth 3
starting at depth 3
ending at depth 3
ending at depth 2
starting at depth 2
starting at depth 3
ending at depth 3
starting at depth 3
ending at depth 3
ending at depth 2
ending at depth 1
ending at depth 0
可以看出,循环中产生了两个相同的递归调用。通过循环的第一次行程在第二次开始之前完成其整个递归执行。两个递归调用完成后,整个调用结束。
另请注意,深度表示没有子节点的base case 或终端/叶节点。您的原始算法将无限递归并炸毁堆栈。
【讨论】:
以上是关于递归调用后的代码递归的主要内容,如果未能解决你的问题,请参考以下文章