【问题标题】: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);
  }
}

【问题讨论】:

  • 您可以使用调试器逐步完成此操作,并亲自查看递归结束的原因。

标签: java recursion


【解决方案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。你甚至部分解释了算法。
    猜你喜欢
    • 2015-01-29
    • 1970-01-01
    • 2016-10-06
    • 2012-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-13
    相关资源
    最近更新 更多