Data structures 偏重左派堆:自上而下版本合并的优势?
我在自学,这要求推理并实现一个偏重的左派堆。这是我的基本实现:Data structures 偏重左派堆:自上而下版本合并的优势?,data-structures,functional-programming,sml,Data Structures,Functional Programming,Sml,我在自学,这要求推理并实现一个偏重的左派堆。这是我的基本实现: (* 3.4 (b) *) functor WeightBiasedLeftistHeap (Element : Ordered) : Heap = struct structure Elem = Element datatype Heap = E | T of int * Elem.T * Heap * Heap fun size E = 0 | size (T (s, _, _, _)) = s fu
(* 3.4 (b) *)
functor WeightBiasedLeftistHeap (Element : Ordered) : Heap =
struct
structure Elem = Element
datatype Heap = E | T of int * Elem.T * Heap * Heap
fun size E = 0
| size (T (s, _, _, _)) = s
fun makeT (x, a, b) =
let
val sizet = size a + size b + 1
in
if size a >= size b then T (sizet, x, a, b)
else T (sizet, x, b, a)
end
val empty = E
fun isEmpty E = true | isEmpty _ = false
fun merge (h, E) = h
| merge (E, h) = h
| merge (h1 as T (_, x, a1, b1), h2 as T (_, y, a2, b2)) =
if Elem.leq (x, y) then makeT (x, a1, merge (b1, h2))
else makeT (y, a2, merge (h1, b2))
fun insert (x, h) = merge (T (1, x, E, E), h)
fun findMin E = raise Empty
| findMin (T (_, x, a, b)) = x
fun deleteMin E = raise Empty
| deleteMin (T (_, x, a, b)) = merge (a, b)
end
现在,在3.4(c)和(d)中,它要求:
目前,merge
分两种方式运行
通行证:由以下内容组成的自上而下通行证:
调用合并
,并进行自底向上的传递
由对助手的调用组成
函数,makeT
。将合并修改为
在一个自上而下的过程中操作。
自上而下有什么好处
merge
的版本有一个延迟
环境同时
环境
我通过简单地内联makeT
更改了merge
函数,但我看不到任何好处,因此我认为我还没有掌握这部分练习的精神。我错过了什么
fun merge (h, E) = h
| merge (E, h) = h
| merge (h1 as T (s1, x, a1, b1), h2 as T (s2, y, a2, b2)) =
let
val st = s1 + s2
val (v, a, b) =
if Elem.leq (x, y) then (x, a1, merge (b1, h2))
else (y, a2, merge (h1, b2))
in
if size a >= size b then T (st, v, a, b)
else T (st, v, b, a)
end
我想我已经找到了一个关于懒惰评估的要点。如果不使用递归合并来计算大小,则在需要子级之前,不需要计算递归调用:
fun merge (h, E) = h
| merge (E, h) = h
| merge (h1 as T (s1, x, a1, b1), h2 as T (s2, y, a2, b2)) =
let
val st = s1 + s2
val (v, ma, mb1, mb2) =
if Elem.leq (x, y) then (x, a1, b1, h2)
else (y, a2, h1, b2)
in
if size ma >= size mb1 + size mb2
then T (st, v, ma, merge (mb1, mb2))
else T (st, v, merge (mb1, mb2), ma)
end
就这些吗?不过,我不确定并发性。我认为就惰性计算而言,您基本上已经掌握了它——如果您每次进行合并时都必须遍历整个数据结构以找出任何东西,那么使用惰性计算并没有多大帮助
至于并发性,我认为问题在于,当一个线程在评估合并时,另一个线程出现并希望查找某个内容时,至少在第一个线程完成合并之前,它将无法完成任何有用的操作。(甚至可能需要更长的时间。)在惰性环境中使用WMERGE-3-4C函数没有任何好处。它仍然完成了原始向下-向上合并所做的所有工作。可以肯定的是,语言系统记忆起来不会更容易。。
在并发环境中对WMERGE-3-4C函数没有好处。每次调用WMERGE-3-4C都会在将责任转移到另一个WMERGE-3-4C实例之前完成所有工作。事实上,如果我们手动消除递归,WMERGE-3-4C可以实现为一个循环,在累积堆栈的同时完成所有工作,然后实现第二个循环,减少堆栈上的工作。第一个循环不会自然地并行,尽管REDUCE可以通过对pairs并行调用函数来运行,直到列表中只剩下一个元素