为什么Fibonacci堆称为Fibonacci堆?

时间:2013-01-15 07:56:22

标签: math data-structures fibonacci fibonacci-heap

Fibonacci heap数据结构名称中包含“Fibonacci”一词,但数据结构中没有任何内容似乎使用Fibonacci数字。根据维基百科的文章:

  

Fibonacci堆的名称来自Fibonacci数字,用于运行时分析。

Fibonacci堆中如何出现这些Fibonacci数?

1 个答案:

答案 0 :(得分:4)

我想给出一个直观的解释,我自己有一个"啊哈!"与时俱进。

树结构实现O(log n)运行时,因为它们能够以高度存储指数数量的项。二叉树可以存储2 ^ h,三元树可以存储3 ^ h,依此类推x ^ h作为通用情况。

x可以小于2吗?当然可以!只要x> 1,我们仍然可以实现日志运行时以及为其高度存储指数级大量项目的能力。但是我们如何建造这样一棵树呢? Fibonacci堆是一个数据结构,其中x≈1.62或Golden Ratio。每当我们遇到黄金比率时,就会有潜伏在某处的斐波那契数字......

Fibonacci堆实际上是一片树林。在一个称为"合并"的过程之后,这些树中的每一个都拥有明确的2个项的精确计数。例如,如果你的Fibonacci堆有15个项,那么它将有4个树,其中包含1个,分别为2,4和8项,如下所示:

enter image description here

"整合的细节"过程是不相关的,但实质上它基本上保持在相同程度的森林中结合树,直到所有树具有不同的程度(尝试cool visualization看看这些树是如何建造的)。由于你可以将任何n写为2的精确幂的总和,因此很容易想象Fibonacci堆的整合树对于任何n都是如何。

好的,到目前为止,我们还没有看到任何与斐波那契数字的直接联系。他们在哪里拍照?它们实际上出现在非常特殊的情况下,这也是为什么Fibonacci堆可以为DECREASE-KEY操作提供O(1)时间的关键。当我们减少一个密钥时,如果新密钥仍然大于父密钥,那么我们不需要做任何其他事情,因为不会违反min-heap属性。但如果不是,那么我们就不能将较小的孩子留在较大的父母身下,因此我们需要将其删除,并从中制作一棵新树。显然,我们不能为每次删除而继续这样做,否则我们最终会得到太高而且不再具有指数项的树,这意味着提取操作不再有O(log n)时间。所以问题是我们可以设置什么规则,因此树的高度仍然具有指数项?聪明的见解是这样的:

We will allow each parent to loose up to one child. If there is a subsequent attempt to remove another child from same parent then we will cut that parent also out of that tree and put it in root list as tree of 1.

以上规则确保树木的高度仍然具有指数项,即使在最坏的情况下也是如此。最糟糕的情况是什么?更糟糕的情况发生在我们让每个父母松散一个孩子的时候。如果父母有> 1个孩子,我们可以选择哪一个摆脱。在这种情况下,让我们摆脱具有最大子树的孩子。因此,在上图中,如果您为每个父项执行此操作,您将拥有大小为1,1,2和3的树。请参阅此处的模式?只是为了好玩,在上面的图表中添加新的4阶树(即16个项目)并猜测在为每个父项运行此规则后你会留下什么:5。我们在这里有一个Fibonacci序列!

由于Fibonacci序列是指数的,每个树仍然保留指数数量的项,因此设法为EXTRACT-MIN操作提供O(log n)运行时。但请注意,DECREASE-KEY现在只需要O(1)。另一个很酷的事情是你可以将任何数字表示为斐波纳契数的总和。例如,32 = 21 + 8 + 3,这意味着如果您需要在Fibonacci堆中保存32个项目,则可以使用分别包含21个,8个和3个项目的3个树来执行此操作。但是"整合" process不会生成具有Fibonacci节点数的树。它们仅在发生DECREASE-KEY或DELETE的更糟糕情况时发生。

进一步阅读

  • Binomial Heap - Fibonacci堆本质上是懒惰的二项式堆。它是一个很酷的数据结构,因为它显示了一种在树中存储指数项的不同方式,它的高度不是二进制堆。
  • Intuition behind Fibonacci Heaps对于想要了解Fibonacci堆的人来说,这是必读的。教科书往往太浅,而且在这个问题上太杂乱了,但是这个SO答案的作者已经把它钉了下来。