joeping

关于尾部的递归优化的斐波那契的数列。

f(n) = f(n-1) * n;

当 n = 1时,f(1) = 1;


f(5) = 5 * f(4) = 5 * 4 * f(3) = 5 * 4 * 3 * f(2) = 5 * 4 * 3 * 2 * f(1) = 120


反过来怎么走,等价于如下形式。

f'(4, 5)

f'(3, 20)

f'(2, 60)

f'(1, 120) 


变成两个参数,就是一个函数。


f(n) = g(n-1, n)

g(x, y) = g(x-1, x * y) 

when x = 1, g(x, y) = y.


用c语言描述就是


int f(int n) {

return g(n-1, n);

}


int g(x, y) {

if (x == 1) return y;

else

return g(x - 1, x * y);

}

其中y的位置以函数参数的形式记录了中间结果。


按原有的方式为

int f(int n) {

if (n == 1) return 1;

else return n * f(n-1);

}

在C语言的环境下,没有做递归优化的时候,这个时候堆栈是没有差别的。原因如下

f(5)

f(4)

f(3)

f(2)

f(1)

然后一级一级的return back。

g(4,5)

g(3, 20)

g(2, 60)

g(1, 120)

然后return back。这是没有做优化的时候。而优化恰好在于

g(4,5)=g(3,20)=g(2,60)=g(1,120).所以此时堆栈上不用保存中间等的返回地址,可以覆盖原有占用堆栈的部分。

应该就没有错了。


  1 #include <stdio.h>

  2

  3 /**

  4  * Description: old function.

  5  */

  6 int fold(int n) {

  7     if (n == 1)

  8         return 1;

  9     else

10         return n * fold(n-1);

11 }

12

13 int g(int x, int y) {

14     if (x == 1)

15         return y;

16     else

17         return g(x - 1, x * y);

18 }

19

20 int fnew(int n) {

21     return g(n - 1, n);

22 }

23

24 int main() {

25     printf("1:%d\n", fold(5));

26     printf("2:%d\n", fnew(6));

27     return 1;

28 }



评论