-
Notifications
You must be signed in to change notification settings - Fork 0
/
heap.ml
78 lines (70 loc) · 1.76 KB
/
heap.ml
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
type 'a heap = {
comp : 'a -> 'a -> bool;
arr : 'a array;
size : int ref
};;
let swap arr i j =
let t = arr.(i) in
arr.(i) <- arr.(j);
arr.(j) <- t;;
let isroot n = n = 0;;
let left n = ((n + 1) * 2) - 1;;
let right n = (n + 1) * 2;;
let parent n = ((n + 1) / 2) - 1;;
let rec swim comp arr i =
if isroot i then () else
if comp arr.(i) arr.(parent i) then
begin
swap arr i (parent i);
swim comp arr (parent i)
end
let rec sink comp size arr i =
if left i >= size then () else
if right i >= size then
begin
if comp arr.(left i) arr.(i) then swap arr (left i) i
end else
begin
if comp arr.(left i) arr.(i) ||
comp arr.(right i) arr.(i) then
begin
if comp arr.(left i) arr.(right i) then
begin
swap arr i (left i);
sink comp size arr (left i)
end else
begin
swap arr i (right i);
sink comp size arr (right i)
end
end
end
exception Full;;
let insert {comp; arr; size} item =
let sz = ! size in
if sz = Array.length arr then raise Full else
begin
arr.(sz) <- item;
swim comp arr sz;
size := sz + 1
end;;
exception Empty;;
let remove_min {comp; arr; size} =
let sz = !size - 1 in
if sz = -1 then raise Empty else
begin
size := sz;
swap arr 0 sz;
sink comp sz arr 0;
arr.(sz)
end;;
let heap_of_array size comp arr =
if size > Array.length arr then raise Full else
let h = { comp = comp;
arr = Array.copy arr;
size = ref size } in
for i = (size / 2) + 1 downto 0 do
sink comp size h.arr i
done;
h;;
(*Compile with 'ocamlc io.mli io.ml heap.mli heap.mli test.ml -o test', to check for problems*)