我正在阅读 Okasaki的纯函数数据结构,并尝试做一些练习。其中之一是证明二项堆merge
需要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 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
很明显,merge
函数会调用自身max(numNodes ts1, numNodes ts2)
次,但由于insTree
的最坏情况为O(log n)
,你能解释一下为什么merge
的时间复杂度是O(log n)
吗?
merge(ts1', ts2')
因此不能包含一个秩<=r'
的树。” 我认为如果ts1
有一个秩为r'
的树,而ts2
不包含一个秩为r'
的树,则可以。 - Justin Raymondr'
",应该只是r'
(刚刚修复了这个)。选择r'
作为最小的秩,因为在ts1'
和ts2'
中都有一棵树。这些树被合并(形成一个秩为r'+1
的树),因此在合并堆merge(ts1', ts2')
中,不再存在秩为r'
的树。之前对insTree
的调用可能会递归一些秩(即,只要ts1'
或ts2'
包含这样一个秩的树,就会递归),但是这种递归必须最迟在秩r'
处停止。此外,从merge
调用的下一个insTree
函数发生在秩r'+1
处。因此,对于每个秩,insTree
最多被调用一次。 - m7thon