方法结束前的递归不是无限循环?

Posted

技术标签:

【中文标题】方法结束前的递归不是无限循环?【英文标题】:Recursion before end of method not an infinite loop? 【发布时间】:2014-03-23 23:40:41 【问题描述】:

我理解尾递归,因为它的功能类似于迭代,在方法调用本身结束时使用新参数。但是当在循环结束的代码之前放置一个递归调用时,为什么它不无限地调用它呢?在下面的代码中,方法 MergeSort_Recursive() 在同一方法中调用自身两次。怎样才能达到对该方法的第二次调用?当第一次调用该方法时,它将比较右>左,然后初始化中间。然后它会调用自己,我们回到方法的顶部,再次进行右>左比较,再次初始化mid,然后再次调用自己并不断重复此步骤。我当然知道这不是它的工作原理,否则这种方法会失败。所以我的问题是这是如何工作的,这两种方法最终是如何被调用的?

static public void MergeSort_Recursive(int [] numbers, int left, int right)

  int mid;

  if (right > left)
  
    mid = (right + left) / 2;
    MergeSort_Recursive(numbers, left, mid);
    MergeSort_Recursive(numbers, (mid + 1), right);

    DoMerge(numbers, left, (mid+1), right);
  

【问题讨论】:

您可以使用调试器逐步完成此操作,并亲自查看递归结束的原因。 【参考方案1】:

存在right > left 为假的基本情况。然后,该函数没有一次调用自己,所以它成功返回。

【讨论】:

【参考方案2】:

注意

if (right > left)

这可以防止递归在right <= left 时继续进行(实际上,right 永远不会小于left,所以它会在right == left 时停止)。它有点像 for 循环中的 i > 0

【讨论】:

其实是right == left停止递归,而不是right < left 或者,您可以输入==,这样会更准确。【参考方案3】:

好吧,最终你会在 leftright 相等的情况下调用它,因此不会输入 if 块,并且递归结束。

例如,如果你用left = 0, right = 4调用它,那么下一个调用是left = 0, right = 2,然后是left = 0, right = 1,最后是left = 0, right = 0。最后一次调用不会进一步递归。

要证明递归结束,请考虑leftright 之间的差距。这每次都减少,所以它最终必须达到 0。它在第一次调用时减少,因为mid 保证为< right,并且在第二次调用时减少,因为mid + 1 保证为> left

【讨论】:

所以当左右相等时,不会进入 if 块。我明白那个。但是实际上何时调用了第二个递归调用? 好吧,在我给出的示例中,当您使用left = 0, right = 4 调用时,第二个调用是left = 3, right = 4。它的第二个调用是left = 4, right = 4,递归结束。 很好的解释。 +1。你甚至部分解释了算法。

以上是关于方法结束前的递归不是无限循环?的主要内容,如果未能解决你的问题,请参考以下文章

循环前的无限缓冲区?

为啥在循环开始时调用 requestAnimationFrame 不会导致无限递归?

PHP二叉树递归遍历无限循环问题

递归无限循环?

JavaScript setTimeout 无递归无限循环

超过了 Django 最大递归深度。无限查看循环