之后的java递归值

时间:2011-07-20 03:19:48

标签: java recursion

我尝试非常简单的测试:

public static void main(String[] args) {
     test(2);
}

public static void test(int i) {
    i--;
    System.out.println("i="+i);
    if (i < 0)
        return;

    System.out.println("test1");
    test(i);
    System.out.println("test2");
    test(i);
}

输出:

i=1
test1
i=0
test1
i=-1
test2
i=-1
test2
i=0
test1
i=-1
test2
i=-1

我无法理解为什么第二次调用(test2)中的变量i在已经为0之后的值为0? 感谢。

7 个答案:

答案 0 :(得分:5)

我发现缩进输出将有助于解释这些事情,这里的每个级别对应于调用堆栈的深度(你有多少递归),序列对应于执行这些操作的时间:

i=1
test1
  i=0 (invoked on the test1 path)
  test1
    i=-1 (invoked on the test1 path)
  test2
    i=-1 (invoked on the test2 path)
test2
  i=0 (invoked on the test2 path)
  test1
    i=-1 (invoked on the test 1 path)
  test2
    i=-1 (invoked on the test 2 path)

请注意,在每个缩进级别下,标题“test1”和“test2”下都有调用,这是因为您在每个标题下递归调用test,因此每个 执行test你两次递送

让我们稍微备份并采取更简单的案例,如果您要执行test(1),您可能会看到:

i=0
  test1
    i=-1
  test2
    i=-1

因为您在标题“test1”和“test2”下调用test,导致两个路径被导航,一个路径位于“test1”标题下,另一个路径位于“test2”标题下。

当您致电test(2)时,您的代码大致会这样做:(省略递归)

(i = 2)
Decrement i  (i = 1)
Print i
Print "test1"
Call test(i) (test(1))
Print "test2"
Call test(i) (test(1))

...并记住,每次调用test(1)时,您的代码大致会这样做:(省略递归)

(i = 1)
Decrement i  (i = 0)
Print i
Print "test 1"
Call test(i) (test(0))
Print "test 2"
Call test(i) (test(0))

如果您使用test(1)块的输出替换第一个块中的每个调用,您将看到它完全生成输出。

基本上,你会得到两个i=0版画,因为你在每个函数调用中都会递归两次

答案 1 :(得分:2)

您的呼叫按以下顺序执行:

test(2);           //initial call;    prints "1"
    test(1);       //test1;           prints "0"
        test(0);   //test1;           prints "-1"
        test(0);   //test2;           prints "-1"
    test(1);       //test2;           prints "0"
        test(0);   //test1;           prints "-1"
        test(0);   //test2;           prints "-1"

答案 2 :(得分:1)

整数按值传递,而不是按引用传递。对测试中的i的更改不会影响调用上下文的i。

答案 3 :(得分:1)

这可能会帮助您将其可视化。连字符的数量表示该级别的调用深度和输出,其中一个连字符是第一个级别(初始调用),两个表示第二个级别,依此类推。

->i=1
->test1
-->i=0
-->test1
--->i=-1
-->test2
--->i=-1
->test2
-->i=0
-->test1
--->i=-1
-->test2
--->i=-1

同样出于调试目的,请考虑在递归时跟踪深度,这样可以很好地标记输出。

public static void test(int i, int depth) {
    i--;
    // ...
    test(i, depth++);
}

答案 4 :(得分:0)

test的每次调用都有自己的i

副本

答案 5 :(得分:0)

Java按值传递参数,而不是通过引用传递参数。根据你传入的内容考虑你的函数调用。像这样:

主要电话:

test(2);

在功能中,你递减i,使其为1,然后调用它:

test(i); // This is equivalent to calling test(1)
test(i); // This is equivalent to calling test(1) again.

所以你的递归函数只是重复,并显示后续值0,-1,-1 - 只显示两次。

答案 6 :(得分:0)

public class Test
{
    public static void main(String[] args)
    {
         test(2); // #1
    }
    public static void test(int i)
    {
        i--; // #2 i = 2 -> 1 #7 i = 1 -> 0 #12 i = 0 -> -1 #18 i = 0 -> -1 #24 i = 1 -> 0 #29 i = 0 -> -1 #35 i = 0 -> -1
        System.out.println("i="+i); // #3 i = 1 #8 i = 0 #13 i = -1 #19 i = -1 #25 i = 0 #30 i = -1 #36 i = -1
        if (i < 0) // #4 i = 1 #9 i = 0 #14 i = -1 #20 i = -1 #26 i = 0 #31 i = -1 #37 i = -1
            return; // #15 i = -1 #21 i = -1 #32 i = -1 #38 i = -1

        System.out.println("test1"); // #5 i = 1 #10 i = 0 #27 i = 0
        test(i); // #6 i = 1 #11 i = 0 #28 i = 0
        System.out.println("test2"); // #16 i = 0 #22 i = 1 #33 i = 0
        test(i); // #17 i = 0 #23 i = 1 #34 i = 0
    }
}

<强>输出:

i=1     // #3
test1   // #5
i=0     // #8
test1   // #10
i=-1    // #13
test2   // #16
i=-1    // #19
test2   // #22
i=0     // #25
test1   // #27
i=-1    // #30
test2   // #34
i=-1    // #36