简体   繁体   English

了解递归调用循环的工作方式

[英]Understanding how a loop of recursive calls work

I'm really new to recusivity, and i stumbled across an exercise in which we have a loop making several recursive calls, and i did not understand, how it is working. 我真的对恢复性很陌生,偶然发现了一个练习,在这个练习中,我们有一个循环进行多次递归调用,但我不明白它是如何工作的。

Look at the example below : 看下面的例子:

int calculateSomething (int n) {

 if (n > 100)
  for (int i = 0; i < 10; i++)
   calculateSomething(n+1);
}

Suppose i make a first call to calculateSomething(200), how many calls i'm gonna have ? 假设我第一次拨打了calculateSomething(200),我将要接多少个电话? At first glimpse i would say 100*10, so 1000 calls ? 乍一看,我会说100 * 10,所以1000个电话?

Does "i" goes along way to 10 for each call ? 每个呼叫是否都将“ i”提高到10? Or it makes a call for each value of "i" ? 还是调用每个“ i”值?

I'm sorry to ask such a question but i'm really blocked XD 很抱歉提出这样的问题,但我确实阻止了XD

Thanks in advance ! 提前致谢 !

First of all, your example code will lend on an infinite loop, if( n>100 ) will be avaluated as TRUE on all your recursive calls because your "n" value always increase. 首先,您的示例代码将无限循环使用,因为在您的所有递归调用中if( n>100 )都会被评估为TRUE,因为您的“ n”值始终会增加。 calculateSomething(n+1)

If you call calculateSomething(200) , the first recursive call will be inside the for loop with i=0 , CalclulateSomething(201) 如果您调用calculateSomething(200) ,则第一个递归调用将在for循环内,且i=0CalclulateSomething(201)

Then forget about the next iterations of the for loop until the recursive call ends , and as I explained before, it will never happen. 然后忘了for循环的下一个迭代,直到递归调用结束为止,并且正如我之前解释的那样,它将永远不会发生。

calculateSomething(200)
  -> i=0 calculateSomething(201)
    -> i=0 calculateSomething(202)
      -> i=0 calculateSomething(203)
        -> ...infinite...

Take the next code as example: (Fixed the infinite loop, and reduced the values for explanation) 以下面的代码为例:(修复了无限循环,并减小了值进行说明)

int calculateSomething (int n) {

 if (n < 3)
  for (int i = 0; i < 3; i++)
   calculateSomething(n+1);
}

The recursive calls will be: 递归调用将是:

calculateSomething(0)
  -> i=0 calculateSomething(1)

    -> i=0 calculateSomething(2)

       -> i=0 calculateSomething(3)
         -> end. if (n < 3) = FALSE
       -> i=1 calculateSomething(3)
         -> end. if (n < 3) = FALSE
       -> i=2 calculateSomething(3)
         -> end. if (n < 3) = FALSE

     -> i=1 calculateSomething(2)

       -> i=0 calculateSomething(3)
         -> end. if (n < 3) = FALSE
       -> i=1 calculateSomething(3)
         -> end. if (n < 3) = FALSE
       -> i=2 calculateSomething(3)
         -> end. if (n < 3) = FALSE

     -> i=2 calculateSomething(2)

       -> i=0 calculateSomething(3)
         -> end. if (n < 3) = FALSE
       -> i=1 calculateSomething(3)
         -> end. if (n < 3) = FALSE
       -> i=2 calculateSomething(3)
         -> end. if (n < 3) = FALSE

  -> i=1 calculateSomething(1)

     -> i=0 calculateSomething(2)

       -> i=0 calculateSomething(3)
         -> end. if (n < 3) = FALSE
       -> i=1 calculateSomething(3)
         -> end. if (n < 3) = FALSE
       -> i=2 calculateSomething(3)
         -> end. if (n < 3) = FALSE

     -> i=1 calculateSomething(2)

       -> i=0 calculateSomething(3)
         -> end. if (n < 3) = FALSE
       -> i=1 calculateSomething(3)
         -> end. if (n < 3) = FALSE
       -> i=2 calculateSomething(3)
         -> end. if (n < 3) = FALSE

     -> i=2 calculateSomething(2)

       -> i=0 calculateSomething(3)
         -> end. if (n < 3) = FALSE
       -> i=1 calculateSomething(3)
         -> end. if (n < 3) = FALSE
       -> i=2 calculateSomething(3)
         -> end. if (n < 3) = FALSE

   -> i=2 calculateSomething(1)

     -> i=0 calculateSomething(2)

       -> i=0 calculateSomething(3)
         -> end. if (n < 3) = FALSE
       -> i=1 calculateSomething(3)
         -> end. if (n < 3) = FALSE
       -> i=2 calculateSomething(3)
         -> end. if (n < 3) = FALSE

     -> i=1 calculateSomething(2)

       -> i=0 calculateSomething(3)
         -> end. if (n < 3) = FALSE
       -> i=1 calculateSomething(3)
         -> end. if (n < 3) = FALSE
       -> i=2 calculateSomething(3)
         -> end. if (n < 3) = FALSE

     -> i=2 calculateSomething(2)

       -> i=0 calculateSomething(3)
         -> end. if (n < 3) = FALSE
       -> i=1 calculateSomething(3)
         -> end. if (n < 3) = FALSE
       -> i=2 calculateSomething(3)
         -> end. if (n < 3) = FALSE

If you want to calculate the number of times your function is called, you can simply add a conunter and increment it for every call, something like: 如果要计算函数被调用的次数,可以简单地添加一个conunter并为每个调用增加它,例如:

int counter = 0;  // declaring it on a global scope

int calculateSomething (int n) {

    counter++;

    if (n < 3)
      for (int i = 0; i < 3; i++)
       calculateSomething(n+1);
    }

The program you had given does not have a return statement even though return type is int. 即使返回类型为int,您所给的程序也没有return语句。 Moreover it will go on infinitely because there is no end condition. 而且,由于没有结束条件,它将无限进行。

This would be the execution cycle 这将是执行周期

call 1: n=200 i=0 calculateSomething(201) 通话1:n = 200,i = 0计算方法(201次)

call 2: n=201 i=0 calculateSomething(202) 通话2:n = 201,i = 0calculateSomething(202)

call 3: n=202 i=0 calculateSomething(203) .... 通话3:n = 202,i = 0calculateSomething(203)...。

Does "i" goes along way to 10 for each call ? 每个呼叫是否都将“ i”提高到10? Or it makes a call for each value of "i" ? 还是调用每个“ i”值?

Makes a call for each value of i. 调用i的每个值。 Recursion works with a stack (Last in First out). 递归适用于堆栈(后进先出)。 In simple program say I call Method1 from main and Method2 from Method1, the stack that would look like this 在简单的程序中,我从main调用Method1并从Method1调用Method2,看起来像这样的堆栈

Method2 方法2

Method1 方法1

main 主要

Basically the last one called will be at the top and once that completes it will go to next one. 基本上,最后一个调用将在顶部,一旦完成,它将转到下一个。

Since you are new to this start with a simpler example like factorial 由于您是新手,因此从一个简单的示例(例如阶乘)开始

public static int factorial(int n) {
    if (n == 0) {
        return 1;
    } else {
        System.out.println(n + " "+ (n-1));
        return n * factorial(n - 1);
    }
}

If you call factorial(3) then stack would look like 如果调用factorial(3),则堆栈看起来像

1 (since factorial(1-1) ie factorial(0) is 0) 1(因为阶乘(1-1),即阶乘(0)为0)

1 * factorial(1-1) 1 *阶乘(1-1)

2 * factorial(2-1) 2 *阶乘(2-1)

3 * factorial(3-1) 3 *阶乘(3-1)

factorial(3) ---> the actual method call factorial(3)->实际方法调用

Now every time a call returns here it will replace the factorial(n-1) in the one below it with the actual value ie 现在,每次调用返回此处,它将用实际值替换其下面的一个因子(n-1),即

factorial(1-1) will be replaced by 1 阶乘(1-1)将替换为1

factorial(2-1) will be replaced by 1 * 1 阶乘(2-1)将替换为1 * 1

factorial(3-1) will be replaced by 2 * (1 * 1) 阶乘(3-1)将替换为2 *(1 * 1)

factorial(3) becomes 3 * (2 * (1 * 1)) factorial(3)变为3 *(2 *(1 * 1))

Hope this helps. 希望这可以帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM