Смещенные по весу левые кучи: преимущества нисходящей версии слияния?

Я занимаюсь самообучением Чисто функциональные структуры данных Окасаки, теперь в упражнении 3.4 , которое просит обдумать и реализовать смещенная левая куча. Это моя основная реализация:

(* 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), он спрашивает:

В настоящее время слияние работает в двух проходит: проход сверху вниз, состоящий из вызовы слияния и восходящего прохода состоящий из обращений к помощнику функция, makeT . Измените merge на работать в один проход сверху вниз. Какие преимущества даст нисходящий версия слияния есть в ленивом окружающая обстановка? Одновременно окружение?

Я изменил функцию merge , просто вставив makeT , но я не вижу каких-либо преимуществ, поэтому думаю, что не понял дух этих частей упражнение. Чего мне не хватает?

  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

Это все? Я не уверен насчет параллелизма.

6
задан Bill the Lizard 26 September 2012 в 00:21
поделиться