-
Notifications
You must be signed in to change notification settings - Fork 0
/
StableHeap.mo
122 lines (106 loc) · 3.23 KB
/
StableHeap.mo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/// Priority Queue
///
/// This module provides purely-functional priority queue based on leftist heap
import I "mo:base/Iter";
import L "mo:base/List";
import O "mo:base/Order";
import P "mo:base/Prelude";
import R "mo:base/Result";
module {
private type Tree<T> = ?(Int, T, Tree<T>, Tree<T>);
// private type Result<T> = R.Result<(?T, Tree<T>), >;
public func default<T>() : Tree<T>{
var heap : Tree<T> = null;
heap
};
/// Insert an element to the heap
public func put<T>(
heap : Tree<T>,
x : T,
ord : (T, T) -> O.Order
) : Tree<T> {
let h = merge(heap, ?(1, x, null, null), ord);
h
};
/// Return the minimal element
public func peekMin<T>(
heap : Tree<T>,
ord : (T, T) -> O.Order
) : ?T {
switch heap {
case (null) { null };
case (?(_, x, _, _)) { ?x };
}
};
/// Delete the minimal element
public func deleteMin<T>(
heap : Tree<T>,
ord : (T, T) -> O.Order
) : ?Tree<T>{
switch heap {
case null { null };
case (?(_, _, a, b)) { let h = merge(a, b, ord); ?h };
}
};
/// Remove the minimal element and return its value
public func removeMin<T>(
heap : Tree<T>,
ord : (T, T) -> O.Order
) : ?(?T, Tree<T>) {
switch heap {
case null { (null) };
case (?(_, x, a, b)) {
var newHeap = merge(a, b, ord);
?(?x, newHeap)
};
}
};
/// Convert iterator into a heap in O(N) time.
public func fromIter<T>(iter : I.Iter<T>, ord : (T, T) -> O.Order) : Tree<T>{
var heap = default<T>();
func build(xs : L.List<Tree<T>>) : Tree<T> {
func join(xs : L.List<Tree<T>>) : L.List<Tree<T>> {
switch(xs) {
case (null) { null };
case (?(hd, null)) { ?(hd, null) };
case (?(h1, ?(h2, tl))) { ?(merge(h1, h2, ord), join(tl)) };
}
};
switch(xs) {
case null { P.unreachable() };
case (?(hd, null)) { hd };
case _ { build(join(xs)) };
};
};
let list = I.toList(I.map(iter, func (x : T) : Tree<T> { ?(1, x, null, null) } ));
if (not L.isNil(list)) {
heap := build(list);
};
heap
};
func rank<T>(heap : Tree<T>) : Int {
switch heap {
case null { 0 };
case (?(r, _, _, _)) { r };
}
};
func makeT<T>(x : T, a : Tree<T>, b : Tree<T>) : Tree<T> {
if (rank(a) >= rank(b)) {
?(rank(b) + 1, x, a, b)
} else {
?(rank(a) + 1, x, b, a)
};
};
func merge<T>(h1 : Tree<T>, h2 : Tree<T>, ord : (T, T) -> O.Order) : Tree<T> {
switch (h1, h2) {
case (null, h) { h };
case (h, null) { h };
case (?(_, x, a, b), ?(_, y, c, d)) {
switch (ord(x,y)) {
case (#less) { makeT(x, a, merge(b, h2, ord)) };
case _ { makeT(y, c, merge(d, h1, ord)) };
};
};
};
};
}