1 (* Copyright (C) 1999-2006, 2008 Henry Cejtin, Matthew Fluet, Suresh
2 * Jagannathan, and Stephen Weeks.
4 * MLton is released under a BSD-style license.
5 * See the file MLton-LICENSE for details.
8 (* Forest of heap ordered trees.
9 * Can be specialized to eager or lazy binomial heaps, fibonacci heaps.
12 functor ForestHeap (S: FOREST_HEAP_STRUCTS): FOREST_HEAP =
19 (* Can't make child a circular list, because the elements aren't defined yet.
21 datatype 'a t = T of {value: 'a Pointer.t,
23 parent: 'a t Pointer.t,
26 child: 'a t Pointer.t,
29 fun destruct(T{prev, value, next, ...}) = (prev, Pointer.! value, next)
31 fun make p = T{value = p,
33 parent = Pointer.null(),
34 next = Pointer.null(),
35 prev = Pointer.null(),
36 child = Pointer.null(),
39 fun new v = make(Pointer.new v)
41 fun dummy v = make(Pointer.null())
43 fun valuePtr(T{value, ...}) = value
44 fun value e = Pointer.!(valuePtr e)
45 fun mark(T{mark, ...}) = mark := true
46 fun unMark(T{mark, ...}) = mark := false
47 fun isMarked(T{mark, ...}) = !mark
48 fun parent(T{parent, ...}) = Pointer.! parent
49 fun hasParent(T{parent, ...}) = not(Pointer.isNull parent)
50 fun setParent(T{parent, ...}, p) = Pointer.:=(parent, p)
51 fun clearParent(T{parent, ...}) = Pointer.clear parent
52 fun next(T{next, ...}) = next
53 fun prev(T{prev, ...}) = prev
54 fun child(T{child, ...}) = child
55 fun numChildrenRef(T{numChildren, ...}) = numChildren
56 fun numChildren e = !(numChildrenRef e)
57 fun incNumChildren e = Int.inc(numChildrenRef e)
58 fun decNumChildren e = Int.dec(numChildrenRef e)
59 val equals = fn (e, e') => Pointer.eq(valuePtr e, valuePtr e')
62 structure CircList = CircularList(structure Elt = DoublyLinked(Elt))
67 type 'a t = (Key.t * 'a) Elt.t
69 fun key(e: 'a t) = #1(value e)
70 fun value(e: 'a t) = #2(Elt.value e)
71 fun setKey(e, k) = Pointer.:=(valuePtr e, (k, value e))
75 then let val p = parent e
76 in if Key.<(key e, key p)
77 then (Pointer.swap(valuePtr e, valuePtr p) ;
84 (*--------------------------------------------------------*)
86 (*--------------------------------------------------------*)
88 datatype 'a t = T of {size: int ref,
89 roots: (Key.t * 'a) CircList.t,
90 min: 'a Elt.t Pointer.t}
92 fun sizeRef (T{size, ...}) = size
93 fun size h = !(sizeRef h)
94 fun setSize(h,n) = sizeRef h := n
95 fun incSize h = Int.inc(sizeRef h)
96 fun decSize h = Int.inc(sizeRef h)
98 fun roots (T{roots, ...}) = roots
100 fun min(T{min, ...}) = Pointer.! min
102 fun clearMin(T{min, ...}) = Pointer.clear min
104 fun updateMin(T{min, ...}, e) =
105 if Pointer.isNull min orelse Key.<(Elt.key e, Elt.key(Pointer.!min))
106 then Pointer.:=(min, e)
110 (CircList.insert(roots h, e)
113 fun isEmpty h = size h = 0
116 fun linkPC(parent, child) =
117 (Elt.incNumChildren parent
118 ; CircList.insert(Elt.child parent, child)
119 ; Elt.setParent(Elt.parent child, parent)
123 (* pre: numChildren e = numChildren e' *)
124 if Key.<(Elt.key e, Elt.key e')
129 fun unlink e = let val p = Elt.parent e
130 in Elt.decNumChildren p
131 ; CircList.delete(Elt.child p, e)
139 in val phi = (1.0 + (Real.sqrt 5.0)) / 2.0
140 fun maxNumChildren h = floor(log(phi, fromInt(size h)))
145 if size h = 0 then ()
146 else let val a = Array.new(maxNumChildren h + 1, NONE)
148 let val n = Elt.numChildren e
149 in case Array.sub(a,n) of
150 NONE => Array.update(a,n, SOME e)
151 | SOME e' => (Array.update(a,n, NONE)
152 ; insertIntoA(link(e, e')))
154 in CircList.deleteEach(roots h, insertIntoA)
155 ; Array.foreach(a, fn NONE => () | SOME e => addRoot(h, e))
159 (*--------------------------------------------------------*)
160 (* Constructors: empty, insert, new *)
161 (*--------------------------------------------------------*)
163 fun empty() = T{size = ref 0,
164 roots = CircList.empty(),
165 min = Pointer.null()}
167 fun insertLazy(h, k, v) =
168 let val e = Elt.new(k, v)
169 in (incSize h ; addRoot(h, e) ; e)
172 fun insertEager(h, k, v) =
173 let val e = insertLazy(h, k, v)
174 in (consolidate h ; e)
179 in (List.foreach(kvs, fn (k, v) => (insertLazy(h, k, v) ; ())) ;
183 fun newEager kvs = let val h = newLazy kvs
184 in (consolidate h ; h)
187 (*--------------------------------------------------------*)
189 (*--------------------------------------------------------*)
196 ; CircList.delete(rs, m)
197 ; CircList.foreach(c, Elt.clearParent)
198 ; CircList.splice(rs, c)
203 (*--------------------------------------------------------*)
205 (*--------------------------------------------------------*)
207 fun sift(_, e, _) = Elt.siftUp e
211 andalso Key.<(k, Elt.key(Elt.parent e))
212 then let val rs = roots h
213 fun cut e = if Elt.hasParent e
214 then let val p = Elt.parent e
216 ; CircList.insert(rs, e)
226 fun decreaseKey(h, e, k) =
227 if Key.>(k, Elt.key e) then Error.bug "decreaseKey"
228 else (Elt.setKey(e, k); updateMin(h, e))
230 fun decreaseKeySift(h, e, k) =
231 (decreaseKey(h, e, k)
234 fun decreaseKeyCut(h, e, k) =
235 (decreaseKey(h, e, k)
238 (*--------------------------------------------------------*)
240 (*--------------------------------------------------------*)
242 fun delete(decreaseKey, h, e) =
243 let val k = Elt.key e
244 in decreaseKey(h, e, Key.smallest)
249 fun deleteSift(h, e) = delete(decreaseKeySift, h, e)
251 fun deleteCut(h, e) = delete(decreaseKeyCut, h, e)
253 (*--------------------------------------------------------*)
255 (*--------------------------------------------------------*)
258 (setSize(h, size h + size h')
259 ; CircList.splice(roots h, roots h'))
261 fun unionEager(h, h') = (union(h, h'); consolidate h)
263 fun unionLazy(h, h') =
265 ; updateMin(h, min h') handle Min => ())
267 (*--------------------------------------------------------*)
269 (*--------------------------------------------------------*)
271 fun output(heap, outputValue, out) = Error.unimplemented "output"
273 (*--------------------------------------------------------*)
274 (* Well-Formed Test *)
275 (*--------------------------------------------------------*)
278 fun sizeInTree e = 1 + sizeInTrees (CircList.T (Elt.children e))
279 and sizeInTrees l = CircList.fold l 0 (fn (e,n) => n + sizeInTree e)
280 fun sizeInHeap h = sizeInTrees (roots h)
282 let val min = ref NONE
283 fun updateMin e = (case !min of
284 NONE => min := SOME e
285 | SOME e' => if Key.<(Elt.key e, Elt.key e')
288 in (CircList.foreach (roots h) updateMin ;
291 | NONE => bug "findMin")
293 fun isTreeWellFormed e =
294 let fun isChildWellFormed e' = (Elt.equals(e, Elt.parent e')
295 andalso Key.<=(Elt.key e, Elt.key e')
296 andalso isTreeWellFormed e')
297 val cs = CircList.T (Elt.children e)
298 in Elt.numChildren e = CircList.length cs
299 andalso CircList.forall cs isChildWellFormed
302 fun isFibonacciHeap h =
303 CircList.forall (roots h) isTreeWellFormed
304 andalso size h = sizeInHeap h
306 orelse Key.equals(Elt.key (min h), Elt.key (findMin h)))