递归调用后的代码递归

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 或终端/叶节点。您的原始算法将无限递归并炸毁堆栈。

【讨论】:

以上是关于递归调用后的代码递归的主要内容,如果未能解决你的问题,请参考以下文章

算法递归

在递归函数参数中修改列表时会发生啥

递归函数

递归函数实例助理解

递归算法

[java基础]递归调用