二元堆的融合/合并是一次还是两次完成?

时间:2012-07-13 00:34:58

标签: data-structures functional-programming binomial-heap

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是较大堆的大小。

0 个答案:

没有答案