【问题标题】:stack call order Fibonacci clarification堆栈调用顺序斐波那契澄清
【发布时间】:2015-04-04 11:53:27
【问题描述】:

我试图澄清递归调用的执行顺序。我通过这个链接阅读: Dynamic programming and Divide and conquer

函数是这样写的:

int Fibonacci(int n) {
    if (n <= 1) return n;

    return Fibonacci(n - 1) + Fibonacci(n - 2);
}

调用顺序是这样描述的:

如果你追踪计算斐波那契(4)的调用,我们得到
Fibonacci(4) 调用 Fibonacci(3) 和 Fibonacci(2)
Fibonacci(3) 调用 Fibonacci(2) 和 Fibonacci(1)
Fibonacci(2) 调用 Fibonacci(1) 和 Fibonacci(0)
Fibonacci(2)(另一个)调用 Fibonacci(1) 和 Fibonacci(0)
斐波那契(1) 终止。
斐波那契(1) 终止。
斐波那契(1) 终止。
斐波那契(0) 终止。 Fibonacci(0) 终止。

这带来了两个问题:

(1) 对于此代码:

return Fibonacci(n - 1) + Fibonacci(n - 2);

+ 号左侧的调用总是在右侧调用之前被调用吗?我认为我们得到了某种深度优先的函数调用链,其中直线调用 Fib(5)...Fib(4)...Fib(3)...Fib(2)...Fib( 1) 在树分支过程中调用其他任何内容之前连续调用。这是真的吗?

(2) 我不明白为什么分支会按此顺序终止: 斐波那契(1) 终止。 斐波那契(1) 终止。 斐波那契(1) 终止。 斐波那契(0) 终止。 Fibonacci(0) 终止。

我认为终止顺序只是树底部从左到右的叶子顺序: 1 0 1 1 0

感谢您对此的任何见解。

【问题讨论】:

    标签: recursion call fibonacci


    【解决方案1】:

    我猜你是对的。我只是做了一个小测试:

    int fibo(int n) {
        if (n <= 1) return n;
        System.out.println("fibo " + n + " calls fibo " + (n - 1) + " and fibo " + (n - 2));
        int f1 = fibo(n - 1);
        System.out.println("fibo " + (n - 1) + " terminates");
        int f2 = fibo(n - 2);
        System.out.println("fibo " + (n - 2) + " terminates");
        return f1 + f2;
    }
    

    得到:

    fibo 4 calls fibo 3 and fibo 2
    fibo 3 calls fibo 2 and fibo 1
    fibo 2 calls fibo 1 and fibo 0
    fibo 1 terminates
    fibo 0 terminates
    fibo 2 terminates
    fibo 1 terminates
    fibo 3 terminates
    fibo 2 calls fibo 1 and fibo 0
    fibo 1 terminates
    fibo 0 terminates
    fibo 2 terminates
    

    如您所见,基本情况的终止顺序是 1 0 1 1 0。

    【讨论】:

      【解决方案2】:

      您没有指定语言,因此当您在一行中有两个调用时,调用顺序无法保证。一些语言或编译器指定它们会做什么,而另一些则没有。

      假设从左到右评估,我将事情分解为带有打印语句的显式调用,以明确显示事情发生的位置。由于没有指定语言,我在 Ruby 中执行此操作:

      def fib(n)
        return n if n <= 1 
        puts "fib(#{n}) calls fib(#{n-1})"
        f1 = fib(n-1)
        puts "fib(#{n-1}) returns to fib(#{n})"
        puts "fib(#{n}) calls fib(#{n-2})"
        f2 = fib(n-2)
        puts "fib(#{n-2}) returns to fib(#{n})"
        f1 + f2
      end
      

      它产生了以下输出:

      irb(main):011:0> fib(4)
      fib(4) calls fib(3)
      fib(3) calls fib(2)
      fib(2) calls fib(1)
      fib(1) returns to fib(2)
      fib(2) calls fib(0)
      fib(0) returns to fib(2)
      fib(2) returns to fib(3)
      fib(3) calls fib(1)
      fib(1) returns to fib(3)
      fib(3) returns to fib(4)
      fib(4) calls fib(2)
      fib(2) calls fib(1)
      fib(1) returns to fib(2)
      fib(2) calls fib(0)
      fib(0) returns to fib(2)
      fib(2) returns to fib(4)
      => 3
      

      我认为这很清楚地说明了正在做什么以及以什么顺序。

      【讨论】:

        猜你喜欢
        • 2012-12-29
        • 2012-05-06
        • 2011-03-24
        • 1970-01-01
        • 2012-12-16
        • 2010-11-24
        • 2018-11-09
        • 2016-11-18
        • 2010-12-19
        相关资源
        最近更新 更多