递归方法如何工作?

时间:2015-11-30 15:13:58

标签: java

我在网上发现了这个递归的例子,但我不明白其中发生了什么。

public class MysteryClass {
    public static void mystery(int n) {
        if (n > 0) {
            mystery(n-1);
            System.out.println(n * 4);
            mystery(n-1);
        }
    }
    public static void main(String[] args) {
        MysteryClass.mystery(2);
    }
}

输出

4
8
4

我的理解是

  1. 2大于0
  2. 2 - 1 = 1
  3. 1大于0
  4. 1 - 1 = 0
  5. 0不大于0
  6. 现在我们跳到这一行:System.out.println(n * 4);
  7. 1 * 4 = 4
  8. 2 * 4 = 8
  9. 在这里,我不明白为什么我会再获得一个“4”的输出
  10. 第9步发生了什么?

    我使用了调试器,但仍然不明白。

7 个答案:

答案 0 :(得分:13)

MysteryClass.mystery(2);
    if (2 > 0) (true) ---> mystery(2-1);
    |   if(1 > 0) (true) ---> mystery (1-1); // Action (A)
    |   |   if(0 > 0) (false) ---> // do nothing 
    |   |     
    |   System.out.println(1 * 4);
    |   mystery(1-1);
    |
    System.out.println(2 * 4);
    mystery(2-1); ---> // repeat action (A)

答案 1 :(得分:5)

如果您使用 mystery(n-1); System.out.println(n * 4); mystery(n-1);

运行此代码
System.out.println(n * 4);

这意味着两次完全神秘(1)。首先它运行神秘(1)获得输出4,但接下来的两个神秘(0)递归以静脉结束。因此它继续

{{1}}

哪个是8

然后再次打开神秘(1)打印4。

答案 2 :(得分:5)

我只能通过考虑如果我复制并粘贴所有代码会发生什么来理解递归,以便它们都在同一个地方。

您可以将mystery(2)替换为三行

mystery(1);
System.out.println(8);
mystery(1);

因此,您的main方法也可以说

public static void main(String[] args) {
    mystery(1);
    System.out.println(8);
    mystery(1);
}

您可以通过

替换这两个mystery(1);来电
mystery(0);
System.out.println(4);
mystery(0);

这意味着main方法也可以说

public static void main(String[] args) {
    mystery(0);
    System.out.println(4);
    mystery(0);
    System.out.println(8);
    mystery(0);
    System.out.println(4);
    mystery(0);
}

mystery(0);实际上没有做任何事情,所以main也可以说

public static void main(String[] args) {
    System.out.println(4);
    System.out.println(8);
    System.out.println(4);
}

答案 3 :(得分:4)

你正在进行双递归 - 同样的函数被称为TWICE。所以你的执行路径是错误的。请注意以下更改:

  mystery(n-1);   // pretend this is function "A"
  System.out.println(n * 4);
  mystery(n-1);   // pretend this is function "B"
  1. mystery(2)//开始递归
  2. A(2-1) - > A(1)// n> 0,所以调用A()
  3. A(1-1) - > A(0)// n == 0,所以没有任何反应
  4. 从(3)
  5. 返回
  6. println(1 * 4) - > 4
  7. 从(2)
  8. 返回
  9. println(n * 4) - > println(2 * 4) - > 8
  10. B(2-1) - > B(1)//我们回到神秘的原始(1)召唤
  11. A(1-0) - > A(0)//等......

答案 4 :(得分:3)

  

这里我不明白为什么我再一次将4作为输出在步骤9中发生的事情???

因为n未被修改。因此,您将使用mystery(2-1);

再次运行它

答案 5 :(得分:2)

如果你用2代替n,你会看到exacly:

if (2 > 0) {
  mystery(2-1); // prints 4
  System.out.println(2 * 4);
  mystery(2-1); // prints 4
}

您有mystery(2-1);两个电话,其中一个在System.out.println

之前,一个在mystery(2-1);

之后

由于所有<p>The width should be 20 cm</p> 都将打印4,因此结果为4 8 4

答案 6 :(得分:1)

要理解将神秘(n-1)替换成神秘的代码:

int n1 = 2
if (n1 > 0){ // step 1
   int n2 = n1 - 1; // step2: 1
   if (n2 > 0){ // step 3
      int n3 = n2 - 1; // step4: 0   
      if (n3 > 0){ // step 5: false
         ...
      }
      System.out.println(n2 * 4); // step 6: print 4
      int n3_1 = n2 - 1; // step 7: 0   
      if (n3_1 > 0){ // false
         ...
      }
   }

   System.out.println(n1 * 4); // step 8: print 8

   if (n2 > 0){
      int n3 = n2 - 1; // 0   
      if (n3 > 0){ // false
         ...
      }  
      System.out.println(n2 * 4);  // step 9: print 4
      int n3_1 = n2 - 1; // 0   
      if (n3_1 > 0){ // false
         ...
      }
   }

}
}