Java中的递归它是如何工作的?

时间:2015-11-18 14:29:15

标签: java recursion

请在以下代码中解释递归语句的工作原理。

int factR(int n) {
    int result;

    if(n==1) return 1;

    result = factR(n-1) * n;
    return result;
}

我的理解是:

在上面的语句中,factR(n-1)方法调用自身直到结束。假设我们想得到6的阶乘,它将作为参数发送给这个方法。它将作为参数n收到,然后将检查n的值;如果是1那么将返回1。但是如果它不是1,就像我们的情况那样它是6,那么递归语句就会运行。

现在我遇到的问题是第一次n-1变为5并且乘以n,它保持值6,然后它变为30.现在30将GO去哪里?

然后该方法将调用自身,此时n-1变为4,然后乘以n,其中IF保持值“6”,然后4 * 6 = 24,我认为这是错误的。因为如果我们通过这种方式然后在下一个电话中 过程将是这样的,n-1将成为3 * n,其中IF保持相同的值,即6然后它将变为3 * 6 = 18.然后,如果我们相乘则发生下一次调用并且n-1变为2并且假设n保持值6然后2 * 6 = 12,并且最后调用n-1 = 1 * n = 6.我的观点是n-1显然会减少值n-1即6-1 = 5然后5-1 = 4然后4-1 = 3然后3-1 = 2和2-1 = 1。但问题是每次方法调用自身时,n的值是多少?

如果你说当第一次乘法发生时,即“n-1”变为5然后乘以6 = 30并且30存储在“n”然后在下一次呼叫中5-1 = 4 * 30 = 120,然后4-1 = 3 * 120 = 360,然后3-1 = 2 * 360 = 720,最后1 * 720 = 720那么Java如何确定将结果值放回变量n

如果每次方法以这种方式调用自身时,我会放置另一个语句来检查变量result的值是什么,如下所示:

int factR(int n) { 
    int result; 

    if(n==1) return 1; 

    result = factR(n-1)*n ;
    System.out.println(result);
    return result; 
}

然后我得到了这个输出:

2
6
24
120
720
Factorial of 6 is 720

我不明白它在第一次通话中是如何产生2的。值2和然后6,24,120和720来自哪里?我认为我严重陷入了代码的工作中。

4 个答案:

答案 0 :(得分:7)

该函数会扩展,直到达到终止语句(n == 1)。假设n = 6,我们有factR(n-1) * n = factR(5) * 6,但factR(5)是什么?那只是factR(4) * 5,所以我们看到factR(5) * 6 = (factR(4) * 5) * 6。现在请注意factR(1) = 1,我们得到

factR(6) = factR(5) * 6 
         = (factR(4) * 5) * 6 
         = ((factR(3) * 4) * 5) * 6 
         = (((factR(2) * 3) * 4) * 5) * 6 
         = ((((factR(1) * 2) * 3) * 4) * 5) * 6 
         = ((((1 * 2) * 3) * 4) * 5) * 6
         = (((2 * 3) * 4) * 5) * 6
         = ((6 * 4) * 5) * 6
         = (24 * 5) * 6
         = 120 * 6
         = 720

答案 1 :(得分:1)

您可能错过的是n是您的函数本地变量。这意味着对函数的每次调用(可能通过递归与否)都会获得一个新变量n,其中包含该函数的参数。因为它是值类型,所以它被复制而不是对原始值的引用。因此,在一次调用中对它的任何更改都不会影响其他(递归)调用中的变量。

因此,您的函数首先会获得6的副本,并将其减少1作为副本,以便下次调用您的函数。那个电话得到一个"副本" 6-1=5并再次减少 - 依此类推。当它达到1时,它也会返回1。然后它再次通过调用堆栈向上运行,并将最后一次调用的结果与此调用中的局部变量相乘。因此12相乘并返回。该结果与3相乘,依此类推。最后你最终得到了阶乘。

答案 2 :(得分:0)

在java中,我们有一个名为 stack 的东西。

每次方法被另一个方法调用时,它都会被添加到堆栈中。

 ________
|factR(1)| = <prints nothing>
 ________
|factR(2)| = 2
 ________
|factR(3)| = 6
 ________
|factR(4)| = 24
 ________
|factR(5)| = 120
 ________
|factR(6)| = 720

这基本上意味着要完成factR(6)方法,factR(5)必须完成,factR(5)完成,factR(4)必须完成,等等。

factR(6)中,您拨打factR(5)然后等待它完成,因为结果取决于它。

但是,在factR(5)中,您也会进行递归调用,而您必须等待。

依此类推,直到我们达到限制factR(1),这将返回1.

完成factR(1)后,factR(2)可以打印出结果并将结果返回到其父方法,依此类推,直到factR(6)打印出来并返回其结果

答案 3 :(得分:-1)

该方法应该像这样构造,以找到n

的阶乘
int factorial(int n)
{
    if (n == 1)
        return 1;

    return n * factorial(n - 1);
}

在我看来,在递归函数中实例化新变量并不是一个好主意,因为它们只是因为范围而每次调用都会被重置。