python - 无法理解斐波那契代码中的递归和缓存

标签 python algorithm

我正在尝试更好地理解递归和缓存,但我仍在取得有趣的进展(有时我有点慢)。我在理解这段代码时遇到了一些小问题:

# Fibonacci recursive with result storage

class FibonacciStorage:
    _storage = { 0:1, 1:1 }
    @staticmethod
    def _fib(number):
        try: # is this already calculated
            return FibonacciStorage._storage[number]   #searches dict, and if value exists then return it
        except KeyError:
            result = FibonacciStorage._fib(number-1) + FibonacciStorage._fib(number-2)  #this is the actual Fibonacci Formula
            FibonacciStorage._storage[number] = result  #adds result to dictionary
            #print FibonacciStorage._storage #this shows the storage list growing with each iteration.
            return result
    @staticmethod
    def fib(number):  #first function, it has two asserts to basically make sure number is whole/positive and if its okay passes it to _fib(where the real work is done)
        # only do the assert statements once
        assert(isinstance(number,int)),"Needs a whole number" 
        assert(number>0),"Needs a positive whole number"
        return FibonacciStorage._fib(number)

# use a more readable name
getFib = FibonacciStorage.fib

print getFib(50)

我在网上找到了这段代码,并尝试对每一行进行注释以了解它的实际作用。我不明白这是一个递归,它确实循环遍历代码直到给出正确的结果,但我不明白它是如何调用自己的。

起初我以为是这一行:result = FibonacciStorage._fib(number-1) + FibonacciStorage._fib(number-2) 但我很困惑,因为我的 print FibonacciStorage._storage 行显示存储缓存在不断增长,但它下面的行是一个返回函数。我怀疑我不明白 return result 实际上是如何以某种方式再次触发递归的。

我也不确定存储字典是如何让这个程序运行得如此之快的。我对 fib 序列的简单递归需要很长时间(即使我保存了数据),但在这种情况下,如果你立即执行 print getFib(200)。缓存如何让它如此之快?

总结一下,两个问题:

1) 递归实际上是如何被触发的?如果我的打印语句在每个循环中都被访问?

2) 缓存如何比其他 fib 序列加快速度?类结构或@staticmethod 是否有所作为?例如,这似乎是即时的,而 http://en.literateprograms.org/Fibonacci_numbers_(Python 上的那些) 有轻微的延迟。

3) 也许也是出于兴趣,斐波诺契类型的算法规模(拆分并并行运行)是否只是出于兴趣,或者它们是否仅限于一个过程?

任何见解都会有所帮助。

最佳答案

(1) 递归调用在这一行:

result = FibonacciStorage._fib(number-1) + FibonacciStorage._fib(number-2)
//                   here ^                        and here ^

你是对的,这是“实际的斐波那契公式”,根据定义它是递归的。

(2) 缓存极大地加快了速度。不同之处在于持久对象 _storage ,这为您节省了大量的重复工作。惊人的。考虑:

                                 fib(4)
                               /        \
                          fib(3)   +     fib(2)
                         /    \          /     \
                    fib(2) + fib(1)   fib(1) + fib(0)
                    /    \
               fib(1) + fib(0)

这只是 fib(4) ,您已经可以看到冗余。通过简单地缓存 fib(3) 的整数值和 fib(4) ,您将减少 fib(5) 所需的计算次数从 7 到 1。节省的钱只会随着你的增加而增加。

关于python - 无法理解斐波那契代码中的递归和缓存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9628489/

相关文章:

algorithm - 查找图的最大子集

c++ - 围绕点拟合矩形

python错误抑制信号18到win32

algorithm - 哈密​​顿路径和社交图谱算法

python - 如何使用循环根据条件对 Pandas 数据框中的列进行子集化?

python - 用另一个数据帧迭代更新数据帧的值

algorithm - 最快的实时解压算法

c# - 转换十进制

python - 如何在每个子列表的索引[0]处拆分字符串,并使每个拆分索引位于其自己的原始列表中?

python - 清理 Python 服务的正确方法——atexit、signal、try/finally