方法结束前的递归不是无限循环?
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】:
好吧,最终你会在 left
和 right
相等的情况下调用它,因此不会输入 if
块,并且递归结束。
例如,如果你用left = 0, right = 4
调用它,那么下一个调用是left = 0, right = 2
,然后是left = 0, right = 1
,最后是left = 0, right = 0
。最后一次调用不会进一步递归。
要证明递归结束,请考虑left
和right
之间的差距。这每次都减少,所以它最终必须达到 0。它在第一次调用时减少,因为mid
保证为< right
,并且在第二次调用时减少,因为mid + 1
保证为> left
。
【讨论】:
所以当左右相等时,不会进入 if 块。我明白那个。但是实际上何时调用了第二个递归调用? 好吧,在我给出的示例中,当您使用left = 0, right = 4
调用时,第二个调用是left = 3, right = 4
。它的第二个调用是left = 4, right = 4
,递归结束。
很好的解释。 +1。你甚至部分解释了算法。以上是关于方法结束前的递归不是无限循环?的主要内容,如果未能解决你的问题,请参考以下文章