如何将这样的递归跟踪打印出来?

时间:2015-01-14 22:11:16

标签: java recursion

所以我试图打印出Fibonacci序列的递归函数的痕迹。

我的输出应该是这样的:

enter image description here

但是,我不确定如何格式化。我真的不知道从哪里开始。 我试过这个:

private static int fibCount;

public static long fibonacci(int n) {
    fibCount++;
    long result;
    if (n == 0 || n == 1) {
        result = n;
        System.out.printf("fib(%s)-->%s%n", n, result);
    } else {
        result = fibonacci(n - 1) + fibonacci(n - 2);
        System.out.printf("fib(%s)%n", n);
    }
    return result;
}

public static void main(String args[]) {
    fibonacci(5);
}

打印出来

fib(1)-->1
fib(0)-->0
fib(2)
fib(1)-->1
fib(3)
fib(1)-->1
fib(0)-->0
fib(2)
fib(4)
fib(1)-->1
fib(0)-->0
fib(2)
fib(1)-->1
fib(3)
fib(5)

我觉得我需要使用那个fibCount变量(我之所以这么做是因为我认为缩进会依赖它),但我不知道我是否应该这样做。

4 个答案:

答案 0 :(得分:3)

尝试以下方法:

  • 分割你的递归通话(这样你就可以在其间打印当前通话)
  • 传入depth参数以跟踪缩进量

public static long fibonacci(int depth, int n) {
    String indent = new String(new char[depth]).replace('\0', ' ');
    long result;
    if (n == 0 || n == 1) {
        result = n;
        System.out.printf(indent + "fib(%s)-->%s%n", n, result);
    } else {
        long first = fibonacci(depth+1, n - 1);
        System.out.printf(indent + "fib(%s)%n", n);
        long second = fibonacci(depth+1, n - 2);
        result = first + second;
    }
    return result;
}

public static void main(String args[]) {
    fibonacci(0, 5);
}

<强>输出:

    fib(1)-->1
   fib(2)
    fib(0)-->0
  fib(3)
   fib(1)-->1
 fib(4)
   fib(1)-->1
  fib(2)
   fib(0)-->0
fib(5)
   fib(1)-->1
  fib(2)
   fib(0)-->0
 fib(3)
  fib(1)-->1

答案 1 :(得分:2)

您需要在每次调用时传入缩进级别。每次你追索你都可以增加缩进量。

public static long fibonacci(int n) {
    return fibonacci(n, 1);
}

public static long fibonacci(int n, int indent) {
    System.out.printf("%"+indent+"s", "");
    long result;
    if (n == 0 || n == 1) {
        result = n;
        System.out.printf("fib(%s)-->%s%n", n, result);
    } else {
        result = fibonacci(n - 1, indent + 2) + fibonacci(n - 2, indent + 2);
        System.out.printf("fib(%s)%n", n);
    }
    return result;
}

答案 2 :(得分:0)

你应该保留一种缩进计数器,每次输入你的斐波那契函数时它都会递增,每次你离开它时都会减少。

然后,在打印时,在实际打印之前放置与此计数器的当前值一样多的空格。为了更好地观看,您可以放置​​两倍的空间,但这只是个人选择。

答案 3 :(得分:0)

我假设在现实世界中,您只是将这样的跟踪(尤其是使用静态变量的跟踪)作为临时调试措施,并在放入之前删除代码投入生产。如果你想把它留在生产代码中,我会寻找不同的解决方案。

首先,如果您要为此使用静态变量,则需要确保每次递归调用都会在之后恢复其值。最好在finally块中执行此操作,以确保即使在代码内部某处隐藏了return(或出现异常),也始终会发生恢复:

public static long fibonacci(int n) {
    int saveFibCount = fibCount;
    fibCount++;
    try {
        fibCount++;
        long result;
        if (n == 0 || n == 1) {
            result = n;
            System.out.printf("fib(%s)-->%s%n", n, result);
        } else {
            result = fibonacci(n - 1) + fibonacci(n - 2);
            System.out.printf("fib(%s)%n", n);
        }
        return result;
    } finally {
        fibCount = saveFibCount;
    }
}

其次,将此缩进到缩进中:不幸的是,Java没有内置方法来返回n个空格字符串。您可以轻松地编写一个(或者使用Apache Commons中可用的方法),并以这种方式使用它们:

        if (n == 0 || n == 1) {
            result = n;
            System.out.printf("%sfib(%s)-->%s%n", blanks(4*fibCount), n, result);
        } else {
            result = fibonacci(n - 1) + fibonacci(n - 2);
            System.out.printf("%sfib(%s)%n", blanks(4*fibCount), n);
        }

其中blanks(b)返回b个空格字符串。您可以使用StringBuilder创建空白字符串,或类似:

String blanks = String.format("%" + numOfBlanks + "s", "");

[注意:根据对另一个答案的评论,如果numOfBlanks为0,这不起作用。]

或者您可以将fibCount替换为String fibIndent,而不是fibCount++使用

fibIndent += "    ";
保存以前的版本后

要考虑的另一件事:如果这是生产代码,我建议将另一个参数传递给递归例程,而不是使用静态变量。尝试使用递归例程处理静态变量只是杂乱且容易出错,即使在单线程程序中也是如此。递归参数应该是一个值参数或一个不可变对象,每个调用在将它传递给下一个调用之前复制。在这种情况下,&#34;递归深度&#34; (您的fibCount)可能是参数。我不建议传递对所有递归调用将共享的对象的引用,因为这几乎与使用静态变量一样容易出错(尽管更加线程安全)。

[注意:我的职业生涯大部分都花在了递归下降的编译器上,所以很多这些问题对我来说都非常熟悉。]

[最后:我知道这只是为了练习,但不要使用递归来计算斐波纳契数。这样做会给你一个指数算法,而不是像直线循环那样的线性算法。这是因为递归算法执行大量冗余工作,计算相同参数的结果多次。]