递归算法中的奇怪行为,

时间:2015-02-11 13:39:06

标签: java algorithm recursion

我正在编写一个递归算法来计算Java中的Fibonacci数,作为编程101课程的一部分。这是代码:

public class Fib {

    public static void main(String[] args) {
        Fib fib = new Fib();
    }

    public Fib() {
        int end = 9;
        long[] nums = new long[2];
        printFib(0, end, nums);
    }

    private void printFib(int i, int end, long[] nums) {
        while(i < end) {
            if(i == 0 || i == 1) {
                nums[i] = 1;
                System.out.println("1");
            } else {
                long fib;
                fib = 0;
                fib += (nums[0] + nums[1]);
                nums[0] = nums[1];
                nums[1] = fib;
                System.out.println(fib);    
            }
            i++;
            printFib(i, end, nums);
        }
    }
}

当我逐步执行该程序时,它按预期工作,直到i变为等于end,该变量告诉printFib方法它应该打印出多少斐波纳契数。如果ì等于end while(i < 1),则按预期返回false,程序将转到上一个},现在您(我) 期望程序返回我最初调用函数的构造函数,程序应该退出,但事实并非如此。该程序返回到while语句,并以某种方式再次评估为false。然后它再次做同样的事情,除了它第二次将i减少1(什么?!)然后在到达if语句时进入else子句。然后,它会在1到2之间一次又一次地从i中减去相同的数量。我已经向我的老师询问了这个问题并且他无法解释它。

如果我将while替换为if,该程序的工作方式与我的预期完全相同,那么可能有一些我不知道的while内容。

修改 所以我现在意识到每次调用方法时i都有一个不同的值存储,当方法退出并且i = end时,程序会回到之前的调用中有不同的价值。

3 个答案:

答案 0 :(得分:4)

您实施了迭代算法来计算斐波那契数列。这就是while循环的作用。在最后进行递归调用 - printFib(i, end, nums) - 是没有意义的。

如果您打算使用递归实现,则不需要整个while循环。

答案 1 :(得分:1)

此代码对我来说并不合适。

我建议你不要用你的方法打印。将值返回到main并打印。

你的递归方法不应该有一个while循环。那个迭代 - 正是你在这里试图避免的。

你的方法应该有一个停止条件和一个自己的调用。这不是你正在做的事情。

这样想:

/**
 * Recursive Fibonnaci
 * User: mduffy
 * Date: 2/11/2015
 * Time: 8:50 AM
 * @link http://stackoverflow.com/questions/28455798/strange-behavior-in-recursive-algorithm/28455863#28455863
 */
public class Math {

    private static Map<Integer, Integer> memo = new ConcurrentHashMap<Integer, Integer>();

    public static void main(String [] args) {
        for (String arg : args) {
            int n = Integer.valueOf(arg);
            System.out.println(String.format("n: %d fib(n): %d", n, fibonnaci(n)));
        }
    }

    public static int fibonnaci(int n) {
        if (n < 0) throw new IllegalArgumentException("index cannot be negative");
        int value = 0;
        if (memo.containsKey(n)) {
            value = memo.get(n);
        } else {
            if (n <= 1) {                
                value = n;
            } else {
                value = fibonnaci(n-1)+fibonnaci(n-2);
            }
            memo.put(n, value);
        }
        return value;
    }
}

答案 2 :(得分:-1)

基本上这种情况正在发生,因为我猜你正在考虑我作为参考,它将影响调用子Fibunacci方法的Fibunacci方法的基本调用。这将最终导致许多对fibunacci方法的调用。

在我看来,循环在你的递归求解方式中没有意义。