【问题标题】:Fibonacci Recursion : Return address?斐波那契递归:返回地址?
【发布时间】:2014-07-05 19:53:59
【问题描述】:

通常当递归调用函数时,堆栈中的返回地址指向函数调用之后的下一条指令。但是在斐波那契代码中,返回地址将指向哪里?即“+”运算符之后的下一行或剩余代码行?

 int Fibonacci(int x) { 
   if (x == 0) return 0;  // Stopping conditions 
   if (x == 1) return 1; 
   return Fibonacci(x - 1)/*cond1*/ + Fibonacci(x - 2);/*cond2*/ 
 }

就我对递归的理解而言,执行 cond1 直到返回 0 或 1 值(即递归树最左侧分支上的深度优先),然后才会执行 cond2,依此类推。那正确吗?当控件执行 Fibonacci(x-1) 时,返回地址会在堆栈中保存为什么(即 EBP)?

        Fibonacci(3) 
           /  \ 
          /    \ 
         /      \ 
        /        \ 
       /          \ 
Fibonacci(2)    *   Fibonacci(1) 
      /     \               \ 
     /       \               \ 
    /         \               \ 
   /           \               \ 
Fibonacci(1) * Fibonacci(0)    1  
   |              | 
   |              | 
   |              | 
   |              | 
   1              0 

【问题讨论】:

  • 是的,你是对的。这种DFS的类型也称为Pre-order,即先访问根,然后遍历左子树,再遍历右子树。

标签: recursion stack fibonacci


【解决方案1】:

是的,您对递归的理解是正确的。它将像 DFS 一样工作。

关于返回地址:回想一下,一行代码不是一条指令。事实上,一行代码可以产生很多指令。

在这种情况下,编译器将生成类似于以下内容的代码:

a = call Fibonacci(x-1)
b = call Fibonacci(x-2)
c = add a, b
return c

所以Fibonacci(x-1) 的返回地址是下一条指令的地址——在这种情况下,是调用Fibonacci(x-2) 的指令。但是请注意,大多数语言并不能保证操作数的求值顺序,您所知道的是+ 的两个操作数在执行加法之前都已被完全求值。实际上,您可以改为:

a = call Fibonacci(x-2)
b = call Fibonacci(x-1)
c = add a, b
return c

重点是,其中一个递归调用的返回地址将是第二次调用的指令地址,而第二次调用的返回地址将是一条ADD 指令。

【讨论】:

  • 所以基本上如果我有 3 个这样的递归调用的总和,那么我会将第一个指向第二个、第二个指向第三个和第三个的返回地址添加到该点之前获得的结果?跨度>
  • @Dubby 是的。但请记住,第 1、第 2 和第 3 次不一定与您查看代码时相同。出于优化原因,编译器可以按照它认为方便的任何顺序评估操作数。
  • 感谢@Filipe Gonçalves
猜你喜欢
  • 2010-12-03
  • 2014-04-02
  • 2017-11-18
  • 2014-01-08
  • 2011-12-14
  • 2012-11-29
  • 2018-04-10
  • 2016-02-21
相关资源
最近更新 更多