尾递归讨论--待完结

按: 本文书于半年前,近日清理电脑内容,暂列于此。

尾递归优化


每一次递归调用都会在栈区引入新的一层方法栈。如递归求解fabonacci值。可写如下实现:
def fabonacci(n)
    return n if n < 2
    return fabonacci(n-1) + fabonacci(n-2)
end
这里调用一次fabonacci(n)将导致fabonacci(n-1)、fabonacci(n-2) 入栈。fabonacci(n-1)也会将fabonacci(n-2)、fabonacci(n-3)入栈。这样,递归次数将以指数增长


➜  expace  ruby -rprofile fabonacci_tail.rb 1
  %   cumulative   self              self     total
 time   seconds   seconds    calls  ms/call  ms/call  name
  0.00     0.00      0.00        2     0.00     0.00  Object#fab
  0.00     0.00      0.00        1     0.00     0.00  Object#fab_recur


➜  expace  ruby -rprofile fabonacci_tail.rb 2
  %   cumulative   self              self     total
 time   seconds   seconds    calls  ms/call  ms/call  name
  0.00     0.00      0.00        3     0.00     0.00  Object#fab
  0.00     0.00      0.00        3     0.00     0.00  Object#fab_recur


➜  expace  ruby -rprofile fabonacci_tail.rb 4
  %   cumulative   self              self     total
 time   seconds   seconds    calls  ms/call  ms/call  name
  0.00     0.00      0.00        5     0.00     0.00  Object#fab
  0.00     0.00      0.00        9     0.00     0.00  Object#fab_recur


➜  expace  ruby -rprofile fabonacci_tail.rb 8
  %   cumulative   self              self     total
 time   seconds   seconds    calls  ms/call  ms/call  name
  0.00     0.00      0.00        9     0.00     0.00  Object#fab
  0.00     0.00      0.00       67     0.00     0.00  Object#fab_recur


➜  expace  ruby -rprofile fabonacci_tail.rb 16
  %   cumulative   self              self     total
 time   seconds   seconds    calls  ms/call  ms/call  name
 87.50     0.07      0.07     3193     0.02     0.24  Object#fab_recur
  0.00     0.08      0.00       17     0.00     0.00  Object#fab


➜  expace  ruby -rprofile fabonacci_tail.rb 24                                                                                                          1 %   cumulative   self              self     total
 time   seconds   seconds    calls  ms/call  ms/call  name
 84.18     3.14      3.14   150049     0.02     0.41  Object#fab_recur
  0.00     3.73      0.00       25     0.00     2.80  Object#fab


以上是求fabonacci(n)时的递归次数统计。 为什么没有fab(32),原因是fab(32)在本环境下profile要很长时间。故未列出。


由此可见,尾递归优化十分有效。


附 测试源代码
➜  expace  cat fabonacci_tail.rb
def fab(n, a, b)
  return a if n < 1
  fab(n-1, b, a+b)
end
def fab_recur(n)
  return n if n < 2
  fab_recur(n-1) + fab_recur(n-2)
end
n=ARGV[0].to_i
fab(n,0,1)
fab_recur(n)




尝试使用了fact尾递归,似乎没有效果。

你可能感兴趣的:(优化,递归,栈)