Commit | Line | Data |
---|---|---|
7f918cf1 CE |
1 | (* Copyright (C) 1999-2006, 2008 Henry Cejtin, Matthew Fluet, Suresh |
2 | * Jagannathan, and Stephen Weeks. | |
3 | * | |
4 | * MLton is released under a BSD-style license. | |
5 | * See the file MLton-LICENSE for details. | |
6 | *) | |
7 | ||
8 | functor BinaryHeap (Key: BOUNDED_ORDER): HEAP = | |
9 | struct | |
10 | ||
11 | structure Array = ResizableArray | |
12 | structure Key = Key | |
13 | ||
14 | (*--------------------------------------------------------*) | |
15 | (* Element *) | |
16 | (*--------------------------------------------------------*) | |
17 | structure Element = | |
18 | struct | |
19 | datatype 'a t = T of {key: Key.t ref, | |
20 | value: 'a, | |
21 | index: int ref} | |
22 | fun new(k, v, i) = T{key = ref k, | |
23 | value = v, | |
24 | index = ref i} | |
25 | fun key(T{key, ...}) = !key | |
26 | fun setKey(T{key, ...}, k) = key := k | |
27 | fun value (T{value, ...}) = value | |
28 | fun index (T{index, ...}) = !index | |
29 | fun setIndex(T{index, ...}, i) = index := i | |
30 | end | |
31 | structure Elt = Element | |
32 | ||
33 | (*--------------------------------------------------------*) | |
34 | (* Heap *) | |
35 | (*--------------------------------------------------------*) | |
36 | ||
37 | datatype 'a t = T of 'a Elt.t Array.t | |
38 | ||
39 | fun empty() = T (Array.fromList []) | |
40 | ||
41 | fun fixIndex(a, i) = Elt.setIndex(Array.sub(a, i), i) | |
42 | fun swap(a, i, j) = (Array.swap(a, i, j) | |
43 | ; fixIndex(a, i) | |
44 | ; fixIndex(a, j)) | |
45 | ||
46 | fun isEmpty (T a) = Array.length a = 0 | |
47 | ||
48 | fun parent(i: int) = (i - 1) div 2 | |
49 | fun left(i: int) = 2 * i + 1 | |
50 | fun right(i: int) = 2 * i + 2 | |
51 | fun key(a, i) = Elt.key(Array.sub(a, i)) | |
52 | fun keyOption(a, i) = Option.map(Array.subOption(a, i), Elt.key ) | |
53 | ||
54 | fun siftUp(a, i) = | |
55 | let fun siftUp i = if i = 0 then () | |
56 | else let val p = parent i | |
57 | in if Key.<(key(a, i), key(a, p)) | |
58 | then (swap(a, i, p); siftUp p) | |
59 | else () | |
60 | end | |
61 | in siftUp i | |
62 | end | |
63 | ||
64 | fun siftDown(a, i) = | |
65 | let | |
66 | fun siftDown i = | |
67 | let val l = left i | |
68 | val r = right i | |
69 | in case keyOption(a, l) of | |
70 | NONE => () | |
71 | | SOME kl => | |
72 | let val min = (case keyOption(a, r) of | |
73 | NONE => l | |
74 | | SOME kr => if Key.<(kl, kr) | |
75 | then l else r) | |
76 | in if Key.<(key(a, i), key(a, min)) then () | |
77 | else (swap(a, i, min); siftDown min) | |
78 | end | |
79 | end | |
80 | in siftDown i | |
81 | end | |
82 | ||
83 | fun new es = | |
84 | let val a = Array.fromList (List.mapi (es, fn (i, (k, v)) => | |
85 | Elt.new (k, v, i))) | |
86 | val start = (Array.length a) div 2 | |
87 | in Int.forDown (start, 0, fn i => siftDown (a, i)) | |
88 | ; T a | |
89 | end | |
90 | ||
91 | fun isEmpty (T a) = Array.length a = 0 | |
92 | ||
93 | fun foreach(T a, f) = Array.foreach(a, f) | |
94 | ||
95 | fun insert(T a, k, v) = | |
96 | let val i = Array.length a | |
97 | val e = Elt.new(k, v, i) | |
98 | in Array.addToEnd(a, e) | |
99 | ; siftUp(a, i) | |
100 | ; e | |
101 | end | |
102 | ||
103 | fun min (h as (T a)) = | |
104 | if isEmpty h then Error.bug "min" | |
105 | else Array.sub(a, 0) | |
106 | ||
107 | fun deleteMin (h as (T a)) = | |
108 | if isEmpty h then Error.bug "deleteMin" | |
109 | else Elt.value (if Array.length a = 1 | |
110 | then Array.deleteLast a | |
111 | else let val min = Array.sub(a, 0) | |
112 | in Array.update(a, 0, Array.deleteLast a) | |
113 | ; fixIndex(a, 0) | |
114 | ; siftDown(a, 0) | |
115 | ; min | |
116 | end) | |
117 | ||
118 | fun decreaseKey(T a, e, k) = | |
119 | if Key.<(Elt.key e, k) then Error.bug "decreaseKey" | |
120 | else (Elt.setKey(e, k); siftUp(a, Elt.index e)) | |
121 | ||
122 | fun delete(h, e) = (decreaseKey(h, e, Key.smallest); deleteMin h; ()) | |
123 | ||
124 | fun union(h, h') = | |
125 | foreach(h', fn e => (insert(h, Elt.key e, Elt.value e); ())) | |
126 | ||
127 | end |