Okasaki在纯功能数据结构(第22页)中的实现分为两部分:一个用于合并林,另一个用于传播进位。这让我觉得比单程版更难分析,也可能更慢。我错过了什么吗?
冈崎的实施:
functor BinomialHeap (Element:ORDERED):HEAP= struct structure Elem=Element datatype Tree = Node of int*Elem.T*Tree list type Heap = Tree list fun link (t1 as Node (r,x1,c1), t2 as Node (_,x2,c2))= if Elem.leq(x1,x2) then Node (r+1,x1,t2::c1) else Node (r+1,x2,t1::c2) fun insTree (t,[])=[t] |insTree (t,ts as t'::ts')= if rank t < rank t' then t::ts else insTree(link(t,t'),ts') fun insert (x,ts)=insTree(Node(0,x,[]),ts) (*just for reference*) fun merge (ts1,[])=ts1 |merge ([],ts2)=ts2 |merge (ts1 as t1::ts1', ts2 as t2:ts2')= if rank t1 < rank t2 then t1::merge(ts1',ts2) else if rank t2 < rank t1 then t2::merge(ts1,ts2') else insTree (link(t1,t2), merge (ts1',ts2')) end
这让我很难分析,因为你必须证明传播所有载体的成本的上限(见下文)。我提出的自上而下合并实现更明显是O(log n),其中n是较大堆的大小:
functor BinomialHeap (Element:ORDERED):HEAP= struct structure Elem=Element datatype Tree = Node of int*Elem.T*Tree list type Heap = Tree list fun rank (Node(r,_,_))=r fun link (t1 as Node (r,x1,c1), t2 as Node (_,x2,c2))= if Elem.leq(x1,x2) then Node (r+1,x1,t2::c1) else Node (r+1,x2,t1::c2) fun insTree (t,[])=[t] |insTree (t,ts as t'::ts')= if rank t < rank t' then t::ts else insTree(link(t,t'),ts') fun insert (x,ts)=insTree(Node(0,x,[]),ts) fun merge(ts1,[])=ts1 |merge([],ts2)=ts2 |merge (ts1 as t1::ts1', ts2 as t2::ts2')= if rank t1 < rank t2 then t1::merge(ts1',ts2) else if rank t2 < rank t1 then t2::merge(ts1,ts2') else mwc(link(t1,t2),ts1',ts2') (*mwc=merge with carry*) and mwc (c,ts1,[])=insTree(c,ts1) |mwc (c,[],ts2)=insTree(c,ts2) |mwc (c,ts1 as t1::ts1', ts2 as t2::ts2')= if rank c < rank t1 then if rank c < rank t2 then c::merge(ts1,ts2) else mwc(link(c,t2),ts1,ts2') else mwc(link(c,t1),ts1',ts2) end
证明Okasaki的实施是O(log n):如果一个套餐是昂贵的&#34; (需要一个或多个链接),然后产生零。因此,当它到达那一点时,下一个昂贵的进位将停止。因此,传播所有进位所需的链接总数不超过传播前二进制表示的总长度,其高于ceil(log n),其中n是较大堆的大小。