对于febonacci heap的分析:
1.extract-min,抽取最小结点花销O(D(n))。因为将min[H]抽取出时,需要实际花销O(D(n))将其子结点并入根表中;其次,合并同度根结点时,由于根表此时最多有T(n)+D(n)-1个根结点,故将同度根结点链接时T(n)+D(n)-1至多实际花销O(T(n)+D(n)),合并后根表至多有D(n)+1个根。利用势能分析法,平摊代价为O(D(n))。其实,由实际代价O(T(n)+D(n))平堆代价为D(n),其实是由根链接减少导致势能减少来支付的。
2.decrease-key,设联级删除c个结点,则根结点由T(n)变为T(n)+(c-1)+1,(c-1个联级点,1个x删除点),势能由T(n)+m(H)变为T(n)+c+2*(m(H)-c+2),故O(c)+4-c=O(1)代价。为什么级联删除c个结点的代价,却是O(1)呢?而不是最坏情况O(lgn)?原因是当删除一个内结点的孩子时,若marked=FALSE,则置为TRUE,有2个“能”,一个用于删除自己,一个用于存储至根,以便同度的根合并。
3.delete-key,调用一次O(1)的decreate-key和O(D(n))的extract-min,故代价为O(D(n))。
4.势能函数T(n)+2*m(H),其中T(n)为根结点、m(H)为marked为TRUE的结点。Why? 斐波那契堆有一个非常重要的性质:度为d的根结点至少有Fd+2个结点,(注:Fi为febonacci数,0 1 1 2 3 5 8 13 ...)以保持D(n)在logn级,这样extract-min和delete-key只需O(logn)。
如何保持此性质呢?1.两个度数相同的根堆合并成二项堆;2.当删除第二个非根结点的孩子时,将该结点移至根形成一新堆。以下为数学证明:
当删除一个结点x时,令y=parent[x]。若marked[y]=TRUE,表明y已经删除1个结点,设D(x)为x结点的度数,x为y的第i个结点,则按照1同度合并操作,当初x与y合并时,x和y都有i-1个度。y至多被删除1个结点,故第y的i个子结点至少有i-2个度。可证size(x)等于size(i)+1,其中,假设size(i)>=Fd+2,归纳法即可证明size(x)>=Fd+2。
又n >= Fd+2 >= 1.56^d,(后Fd+2 >= logn可证),故d<=log1.56(n),即logn。证毕。
这说明只要保证extract-min和delete-key就可lazily维护“松散"的斐波纳契堆性质。而其它时候对于其结构,则允许“无限”松散。
5.对于D(n)如何选取呢?
1.Dn = 1+8*sizeof(long)——由于利用long类型定义堆的度的个数sizeof(long)*8,考虑到可能合并后最大度+1,故二项树度最多不超过1+sizeof(long)*8。
2.利用ceillog2函数,求出当前树结点n的最大度lgn,再+2。
以下是我对于febonacci heap的实现源代码:</