This repository has been archived by the owner on Nov 6, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 21
/
priorityq.mini
126 lines (115 loc) · 3.87 KB
/
priorityq.mini
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
122
123
124
125
126
//
// Copyright 2020, Offchain Labs, Inc. All rights reserved.
//
use core::array::array;
use core::array::array_resize;
type PqItem<T> = struct {
priority: uint,
item: T,
};
type PriorityQ<T> = struct {
size: uint,
capacity: uint,
contents: []PqItem<T>,
};
public throw func priorityq_new<T>() -> PriorityQ<T> {
struct {
size: 0,
capacity: 8,
contents: newarray<PqItem<T> >(8),
}
}
public func priorityq_isEmpty<T>(pq: PriorityQ<T>) -> bool {
pq.size == 0
}
public func priorityq_size<T>(pq: PriorityQ<T>) -> uint {
pq.size
}
public throw func priorityq_get<T>(pq: PriorityQ<T>) -> option<(T, PriorityQ<T>)> {
if priorityq_isEmpty::<T>(pq) {
None
} else {
let ret = pq.contents[0].item;
let newpq = pq with { size: pq.size-1 }
with { contents: pq.contents with { [0] = pq.contents[pq.size-1] } };
Some((ret, pq_pushDown::<T>(newpq, 0)))
}
}
throw func pq_pushDown<T>(pq: PriorityQ<T>, index: uint) -> PriorityQ<T> {
loop {
let firstKidIdx = 2*index+1;
if firstKidIdx >= pq.size {
return pq;
} else if firstKidIdx+1 == pq.size {
// only one kid is in play
let this = pq.contents[index];
let kid = pq.contents[firstKidIdx];
if kid.priority > this.priority {
return pq with { contents: pq.contents with { [index] = kid }
with { [firstKidIdx] = this } };
} else {
return pq;
}
} else {
let this = pq.contents[index];
let firstKid = pq.contents[firstKidIdx];
let secondKidIdx = firstKidIdx+1;
let secondKid = pq.contents[secondKidIdx];
if firstKid.priority > secondKid.priority {
if firstKid.priority > this.priority {
pq = pq with { contents: pq.contents with { [index] = firstKid }
with { [firstKidIdx] = this } };
index = firstKidIdx;
} else {
return pq;
}
} else {
if secondKid.priority > this.priority {
pq = pq with { contents: pq.contents with { [index] = secondKid }
with { [secondKidIdx] = this } };
index = secondKidIdx;
} else {
return pq;
}
}
}
}
}
throw func pq_pushUp<T>(pq: PriorityQ<T>, index: uint) -> PriorityQ<T> {
let this = pq.contents[index];
loop {
if index == 0 {
return pq;
}
let parentIdx = (index-1)/2;
let parent = pq.contents[parentIdx];
if parent.priority >= this.priority {
return pq;
} else {
pq = pq with { contents: pq.contents with { [index] = parent }
with { [parentIdx] = this } };
index = parentIdx;
}
}
}
public throw func priorityq_insert<T>(pq: PriorityQ<T>, item: T, priority: uint) -> PriorityQ<T> {
if pq.size == pq.capacity {
let newCapacity = 8*pq.capacity;
pq = pq with { capacity: newCapacity }
with { contents: unsafecast<[]PqItem<T> >(array_resize(unsafecast<array>(pq.contents), newCapacity, ())) };
}
let index = pq.size;
let newpq = pq with { size: index+1 }
with { contents: pq.contents with { [index] = struct { priority: priority, item: item, } } };
pq_pushUp::<T>(newpq, index)
}
public write throw func priorityq_printAsArray<T>(pq: PriorityQ<T>) -> uint {
let ret = pq.size;
let cont = pq.contents;
let i = 0;
while i < ret {
debug(cont[i]);
i = i+1;
}
ret
}