绪论
Fibonacci Heaps和Complete Heaps一样都是优化版本的堆。Complete Heaps是通过完全二叉树的简单性质来避免堆出现糟糕的退化情况,实际上在一般(最优)情况下各操作的复杂度和一般堆是一样的。
Fibonacci Heaps的优化结合了lazy操作(懒惰标记),散列的一些思想和Fibonacci数的数学性质,在树的结构上不要求一昧的维持平衡(可能也维持了,只是我没有理解),在操作上可以将union(合并),insert(插入),decrease-key(修改某个元素的key值)这三个操作的均摊时间复杂度降低到O(1)。
(decrease-key在国内的教材中往往不做介绍,C++编译器的priority_queue也没有提供这个函数)
所以Fibonacci Heaps在使用优先队列需要进行多次队列中key值修改的算法方面可以做到很好的优化,例如Prim算法,不过我们能够找到的用优先队列实现的普利姆算法,往往用另外的操作(详情见其他文章)替代了修改队列中key值的那一步,对于decrease-key操作这方面介绍的就比较少甚至没有。
Fibonacci Heaps
Fibonacci Heaps从结构上看若干个堆组成的森林,各个堆的堆顶也就是所在堆优先级最高(低)的元素构成的链表。
用一个min指针始终指向堆顶结点构成的链表中优先级最高(低)的元素,即整个Fibonacci Heaps优先级最高(低)的元素。
树中有如下属性:
n表示堆中结点的总个数;rank(x)表示结点x的孩子个数,在还没有进行过lazy标记的情况下,我们尽可能地希望链表中结点的rank值各不相同,在每次extract_min操作中进行调整,可以容忍多个结点rank值为0的情况;trees(H)为森林中树的个数,即链表中结点的个数;marks表示堆中