Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 方法结束前的递归不是无限循环吗?_Java_Recursion - Fatal编程技术网

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

Java 方法结束前的递归不是无限循环吗?,java,recursion,Java,Recursion,我理解尾部递归,因为它的功能类似于迭代,在方法结束时使用新参数调用自身。但是,当递归调用放在循环末尾的代码之前时,为什么它不无限地调用它自己呢?在下面的代码中,MergeSort_Recursive()方法在同一个方法中调用自身两次。该方法的第二次调用将如何到达?当第一次调用该方法时,它将比较right>left,然后初始化mid。然后它调用自身,我们转到该方法的顶部,该方法将再次执行right>left比较,再次初始化mid,然后再次调用自身,并不断重复此步骤。我当然知道这不是它的工作原理,否

我理解尾部递归,因为它的功能类似于迭代,在方法结束时使用新参数调用自身。但是,当递归调用放在循环末尾的代码之前时,为什么它不无限地调用它自己呢?在下面的代码中,MergeSort_Recursive()方法在同一个方法中调用自身两次。该方法的第二次调用将如何到达?当第一次调用该方法时,它将比较right>left,然后初始化mid。然后它调用自身,我们转到该方法的顶部,该方法将再次执行right>left比较,再次初始化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);
  }
}

在一些基本情况下,
right>left
为false。然后,函数一次也不调用自己,因此它成功返回。

在一些基本情况下,
right>left
为false。然后,函数一次也不调用自己,因此它成功返回。

在一些基本情况下,
right>left
为false。然后,函数一次也不调用自己,因此它成功返回。

在一些基本情况下,
right>left
为false。然后,函数没有一次调用它自己,因此它成功地返回。

好吧,最终您将使用
left
right
相等值调用它,因此不会输入
if
块,递归结束

例如,如果您使用
left=0,right=4
调用它,那么下一次调用具有
left=0,right=2
,然后是
left=0,right=1
,最后是
left=0,right=0
。最后一次调用不会再次出现


为了证明递归结束,考虑<代码>左和<代码>右< /代码>之间的间隙。每次都会减少,因此最终必须达到0。第一次调用时它会减小,因为

mid
保证为
,第二次调用时它会减小,因为
mid+1
保证为

好的,最终您将使用
left
right
equal调用它,因此不会输入
if
块,递归结束

例如,如果您使用
left=0,right=4
调用它,那么下一次调用具有
left=0,right=2
,然后是
left=0,right=1
,最后是
left=0,right=0
。最后一次调用不会再次出现


为了证明递归结束,考虑<代码>左和<代码>右< /代码>之间的间隙。每次都会减少,因此最终必须达到0。第一次调用时它会减小,因为

mid
保证为
,第二次调用时它会减小,因为
mid+1
保证为

好的,最终您将使用
left
right
equal调用它,因此不会输入
if
块,递归结束

例如,如果您使用
left=0,right=4
调用它,那么下一次调用具有
left=0,right=2
,然后是
left=0,right=1
,最后是
left=0,right=0
。最后一次调用不会再次出现


为了证明递归结束,考虑<代码>左和<代码>右< /代码>之间的间隙。每次都会减少,因此最终必须达到0。第一次调用时它会减小,因为

mid
保证为
,第二次调用时它会减小,因为
mid+1
保证为

好的,最终您将使用
left
right
equal调用它,因此不会输入
if
块,递归结束

例如,如果您使用
left=0,right=4
调用它,那么下一次调用具有
left=0,right=2
,然后是
left=0,right=1
,最后是
left=0,right=0
。最后一次调用不会再次出现

为了证明递归结束,考虑<代码>左和<代码>右< /代码>之间的间隙。每次都会减少,因此最终必须达到0。第一次调用时它会减小,因为

mid
保证为
,第二次调用时它会减小,因为
mid+1
保证为

注意

if (right > left)
这将防止在for循环中
右0
时继续递归。

请注意

if (right > left)
这将防止在for循环中
右0
时继续递归。

请注意

if (right > left)
这将防止在for循环中
右0
时继续递归。

请注意

if (right > left)

这会阻止递归在for循环中
右0
时继续进行。

您可以使用调试器逐步完成此过程,并亲自查看递归结束的原因。您可以使用调试器逐步完成此过程,并亲自查看递归结束的原因。您可以使用调试器逐步完成此过程,你可以用调试器一步一步地解决这个问题,看看递归为什么会结束。事实上,正是在这种情况下,
right==left
停止递归,而不是
right
。或者,你可以把
=
放在更准确的位置。实际上,在这种情况下,
right==left
停止递归,而不是
right
。或者,你可以把
=
放在更准确的位置。实际上,是
right==left
停止递归,而不是
right
。或者,你可以把
==<