-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathheap.ml
More file actions
103 lines (92 loc) · 2.3 KB
/
heap.ml
File metadata and controls
103 lines (92 loc) · 2.3 KB
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
(* we store pairs of ('v * 'k) in the array to use the default comparison *)
type ('k, 'v) t = {
mutable a: ('v * 'k) array;
mutable n: int;
ht:('k, int) Hashtbl.t }
let one k v =
let ht = Hashtbl.create 1000 in
let a = [|(v,k)|] in
begin
Hashtbl.add ht k 0;
{a; n=1; ht}
end
let size heap = heap.n
let track heap i =
Hashtbl.add heap.ht (snd heap.a.(i)) i
let rec heap_up heap i =
if i = 0 || heap.a.(i) > heap.a.((i-1)/2) then
()
else begin
let tmp = heap.a.(i) in
begin
heap.a.(i) <- heap.a.((i-1)/2);
heap.a.((i-1)/2) <- tmp;
track heap i;
track heap ((i-1)/2);
heap_up heap ((i-1)/2)
end
end
let rec heap_down heap i =
if 2*i+2 < heap.n then begin
if heap.a.(2*i+1) < heap.a.(2*i+2) then begin
if heap.a.(i) > heap.a.(2*i+1) then begin
let tmp = heap.a.(i) in
heap.a.(i) <- heap.a.(2*i+1);
heap.a.(2*i+1) <- tmp;
track heap i;
track heap (2*i+1);
heap_down heap (2*i+1)
end
end
else begin
if heap.a.(i) > heap.a.(2*i+2) then begin
let tmp = heap.a.(i) in
heap.a.(i) <- heap.a.(2*i+2);
heap.a.(2*i+2) <- tmp;
track heap i;
track heap (2*i+2);
heap_down heap (2*i+2)
end
end
end
else begin
if 2*i+1 < heap.n && heap.a.(i) > heap.a.(2*i+1) then begin
let tmp = heap.a.(i) in
heap.a.(i) <- heap.a.(2*i+1);
heap.a.(2*i+1) <- tmp;
track heap i;
track heap (2*i+1);
heap_down heap (2*i+1)
end
else
()
end
let pop heap =
if heap.n <= 0 then failwith "empty heap";
let x = heap.a.(0) and n = heap.n in
begin
Hashtbl.remove heap.ht (snd heap.a.(0));
heap.a.(0) <- heap.a.(n-1);
heap.n <- n - 1;
track heap 0;
heap_down heap 0;
let (v, k) = x in (k, v)
end
let mem heap k =
Hashtbl.mem heap.ht k
let insert heap k v =
begin
heap.n <- heap.n + 1;
if heap.n > (Array.length heap.a) then
heap.a <- (Array.append heap.a (Array.make heap.n (v,k)));
heap.a.(heap.n - 1) <- (v,k);
track heap (heap.n-1);
heap_up heap (heap.n - 1)
end
let decrease heap k v =
let i = Hashtbl.find heap.ht k in begin
if heap.a.(i) > (v, k) then begin
heap.a.(i) <- (v, k);
heap_up heap i
end
end