Fibonacci Heaps——python实现
前言
Fibonacci Heaps的所有内容都在这里 Fibonacci Heaps 可以找到。
简单的概括,斐波那契堆其实是 lazy binomial heaps 的扩展,支持更高效的 decreaseKey(v,k) 和 delete(v). 那么在 lazy binomial heaps实现 的基础上稍作改动和扩展即可。
完整代码和测试代码已上传资源…
functions
大部分操作的实现与 lazy binomial heaps 无异。只是一些细节有所不同:在这里 insert(x) ⟹ \implies ⟹insert(v), 插入的是节点,在扩展的 Binomial Tree节点中需要存是否已丢失孩子的 mark,维护 merge 时保证连进来的 root unmarked, 以及 在coalesce step 中创建箱子的个数,log 的 base…
所以大量的重复内容,merge, insert, extractMin, find_min, coalesce step. updateMin,就不在这里展示了,同样参考前面的实现博客吧。
另外表示方法也同之前一样,双向循环链表,父结点只存一个孩子。
decreaseKey(v, k)
这里唯一的问题就是 cascading cut,级联切割,当我们要 decreaseKey 的 node 的父节点已经损失了孩子。此时为了保证 root 的 order 和其节点数 n 的关系 ϕ r o o t . o r d e r ≤ n \phi^{root.order} \leq n ϕroot.order≤n,即斐波那契数列的性质,所以也要把 node 的 parent 同样切下来,直到遇到没有损失孩子的 parent 或者根。
def decreaseKey(self,v,k):
if k < self.min.data: # update min ptr
self.min = v
v.data = k
if not v.parent: # root, no need to cut
return
new_heap = Fibonacci_Heap()
if v.pre == v: # only one child
assert v.parent.order == 1,'wrong order'
new_heap.head = v
new_heap.min = v
self.merge(new_heap)
v = v.parent
v.Lchild.parent = None
v.Lchild = None
else:
if v.parent.Lchild == v:
v.parent.Lchild = v.sibling
temp = v.parent
v.pre.sibling = v.sibling
v.sibling.pre = v.pre
v.pre = v
v.sibling = v
new_heap.head = v
new_heap.min = v
self.merge(new_heap)
v.parent = None
v = temp
v.order -= 1
while v.parent:
if v.losing_child:
v.losing_child = False
if v.pre == v: # only one child, same as before
assert v.parent.order == 1, 'wrong order'
new_heap.head = v
new_heap.min = v
self.merge(new_heap)
v = v.parent
v.Lchild.parent = None
v.Lchild = None
else:
if v.parent.Lchild == v:
v.parent.Lchild = v.sibling
temp = v.parent
v.pre.sibling = v.sibling
v.sibling.pre = v.pre
v.pre = v
v.sibling = v
new_heap.head = v
new_heap.min = v
self.merge(new_heap)
v.parent = None
v = temp
v.order -= 1
else:
v.losing_child = True
break
delete(v)
delete(v) 的实现非常简单…
def delete(self,v):
self.decreaseKey(v,float('-inf'))
self.extractMin()
结语
有点儿水…
但堆相关这部分内容,从知识搬运消化,到上码实战,总算完啦,液✌。