Skip to content

Commit e0b396c

Browse files
committed
Add a class insertion feature
1 parent fe5b76e commit e0b396c

File tree

1 file changed

+62
-33
lines changed

1 file changed

+62
-33
lines changed

lib/Algorithm/MinMaxHeap.pm6

Lines changed: 62 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,28 @@
11
use v6;
22
unit class Algorithm::MinMaxHeap;
33

4+
use Algorithm::MinMaxHeap::Comparable;
5+
use Algorithm::MinMaxHeap::CmpOperator;
6+
47
has @.nodes;
8+
has Mu $.type;
9+
10+
multi submethod BUILD() {
11+
$!type = Int;
12+
}
513

6-
submethod BUILD() {
14+
multi submethod BUILD(Mu:U :$!type) {
15+
if (Algorithm::MinMaxHeap::Comparable|Cool|Str|Rat|Int|Num ~~ $!type) {
16+
# nothing to do
17+
} else {
18+
die "ERROR: Not compatible type is specified";
19+
}
720
}
821

9-
method insert(Int:D $value) {
22+
method insert($value) {
23+
if (not $value.WHAT ~~ $!type) {
24+
die "ERROR: Not compatible type is inserted";
25+
}
1026
@!nodes.push($value);
1127
self!bubble-up(@!nodes.elems - 1);
1228
}
@@ -28,7 +44,12 @@ method find-max() {
2844
elsif (@!nodes.elems == 2) {
2945
return @!nodes[1];
3046
} else {
31-
return max(@!nodes[1],@!nodes[2]);
47+
if (@!nodes[1] minmaxheap-cmp @!nodes[2] == Order::More) {
48+
return @!nodes[1];
49+
}
50+
else {
51+
return @!nodes[2];
52+
}
3253
}
3354
}
3455

@@ -58,13 +79,13 @@ method pop-max() {
5879
elsif (@!nodes.elems == 2) {
5980
return @!nodes.pop;
6081
}
61-
elsif (@!nodes[1] >= @!nodes[2]) {
82+
elsif (@!nodes[1] minmaxheap-cmp @!nodes[2] == Order::Same|Order::More) {
6283
my $max-value = @!nodes[1];
6384
@!nodes[1] = @!nodes.pop;
6485
self!trickle-down(1);
6586
return $max-value;
6687
}
67-
elsif (@!nodes[1] < @!nodes[2]) {
88+
elsif (@!nodes[1] minmaxheap-cmp @!nodes[2] == Order::Less) {
6889
my $max-value = @!nodes[2];
6990
if (@!nodes.elems > 3) {
7091
@!nodes[2] = @!nodes.pop;
@@ -80,20 +101,28 @@ method pop-max() {
80101
}
81102
}
82103

104+
method !compare($lhs, $rhs) returns Order:D {
105+
if ($!type ~~ Cool) {
106+
return $lhs minmaxheap-cmp $rhs;
107+
} else {
108+
return $lhs.compare-to($rhs);
109+
}
110+
}
111+
83112
method is-empty() returns Bool:D {
84113
return @!nodes.elems == 0 ?? True !! False;
85114
}
86115

87116
method !bubble-up($index) {
88117
if (self!is-minlevel($index)) {
89-
if (self!has-parent($index) and (@!nodes[$index] > @!nodes[self!find-parent($index)])) {
118+
if (self!has-parent($index) and (@!nodes[$index] minmaxheap-cmp @!nodes[self!find-parent($index)] == Order::More)) {
90119
self!swap(@!nodes[$index], @!nodes[self!find-parent($index)]);
91120
self!bubble-up-max(self!find-parent($index));
92121
} else {
93122
self!bubble-up-min($index);
94123
}
95124
} else {
96-
if (self!has-parent($index) and (@!nodes[$index] < @!nodes[self!find-parent($index)])) {
125+
if (self!has-parent($index) and (@!nodes[$index] minmaxheap-cmp @!nodes[self!find-parent($index)] == Order::Less)) {
97126
self!swap(@!nodes[$index], @!nodes[self!find-parent($index)]);
98127
self!bubble-up-min(self!find-parent($index));
99128
} else {
@@ -104,7 +133,7 @@ method !bubble-up($index) {
104133

105134
method !bubble-up-min($index) {
106135
if (self!has-grandparent($index)) {
107-
if (@!nodes[$index] < @!nodes[self!find-grandparent($index)]) {
136+
if (@!nodes[$index] minmaxheap-cmp @!nodes[self!find-grandparent($index)] == Order::Less) {
108137
self!swap(@!nodes[$index], @!nodes[self!find-grandparent($index)]);
109138
self!bubble-up-min(self!find-grandparent($index));
110139
}
@@ -113,7 +142,7 @@ method !bubble-up-min($index) {
113142

114143
method !bubble-up-max($index) {
115144
if (self!has-grandparent($index)) {
116-
if (@!nodes[$index] > @!nodes[self!find-grandparent($index)]) {
145+
if (@!nodes[$index] minmaxheap-cmp @!nodes[self!find-grandparent($index)] == Order::More) {
117146
self!swap(@!nodes[$index], @!nodes[self!find-grandparent($index)]);
118147
self!bubble-up-max(self!find-grandparent($index));
119148
}
@@ -133,15 +162,15 @@ method !trickle-down-min(Int:D $index) {
133162
my %response = self!find-smallest($index);
134163
my ($smallest-index, $is-child) = %response<smallest-index>, %response<is-child>;
135164
if (not $is-child) {
136-
if (@!nodes[$smallest-index] < @!nodes[$index]) {
165+
if (@!nodes[$smallest-index] minmaxheap-cmp @!nodes[$index] == Order::Less) {
137166
self!swap(@!nodes[$smallest-index], @!nodes[$index]);
138-
if (@!nodes[$smallest-index] > @!nodes[self!find-parent($smallest-index)]) {
167+
if (@!nodes[$smallest-index] minmaxheap-cmp @!nodes[self!find-parent($smallest-index)] == Order::More) {
139168
self!swap(@!nodes[$smallest-index], @!nodes[self!find-parent($smallest-index)]);
140169
}
141170
self!trickle-down-min($smallest-index);
142171
}
143172
} else {
144-
if (@!nodes[$smallest-index] < @!nodes[$index]) {
173+
if (@!nodes[$smallest-index] minmaxheap-cmp @!nodes[$index] == Order::Less) {
145174
self!swap(@!nodes[$smallest-index], @!nodes[$index]);
146175
}
147176
}
@@ -152,15 +181,15 @@ method !trickle-down-max(Int:D $index) {
152181
my %response = self!find-largest($index);
153182
my ($largest-index, $is-child) = %response<largest-index>, %response<is-child>;
154183
if (not $is-child) {
155-
if (@!nodes[$largest-index] > @!nodes[$index]) {
184+
if (@!nodes[$largest-index] minmaxheap-cmp @!nodes[$index] == Order::More) {
156185
self!swap(@!nodes[$largest-index], @!nodes[$index]);
157-
if (@!nodes[$largest-index] < @!nodes[self!find-parent($largest-index)]) {
186+
if (@!nodes[$largest-index] minmaxheap-cmp @!nodes[self!find-parent($largest-index)] == Order::Less) {
158187
self!swap(@!nodes[$largest-index], @!nodes[self!find-parent($largest-index)]);
159188
}
160189
self!trickle-down-max($largest-index);
161190
}
162191
} else {
163-
if (@!nodes[$largest-index] > @!nodes[$index]) {
192+
if (@!nodes[$largest-index] minmaxheap-cmp @!nodes[$index] == Order::More) {
164193
self!swap(@!nodes[$largest-index], @!nodes[$index]);
165194
}
166195
}
@@ -172,50 +201,50 @@ method !swap($lhs is raw, $rhs is raw) {
172201

173202
method !find-smallest(Int:D $index) {
174203
my ($smallest-value, $smallest-index, $is-child);
175-
$smallest-value = Inf;
204+
$smallest-value = Any;
176205
$smallest-index = $index;
177206
$is-child = False;
178207

179208
if (self!has-left-child($index)) {
180-
my $left-child;
181-
if ($smallest-value > @!nodes[($left-child = self!find-left-child($index))]) {
209+
my $left-child = self!find-left-child($index);
210+
if ((not $smallest-value.defined) or $smallest-value minmaxheap-cmp @!nodes[$left-child] == Order::More) {
182211
$smallest-value = @!nodes[$left-child];
183212
$smallest-index = $left-child;
184213
$is-child = True;
185214
}
186215

187216
if (self!has-left-child($left-child)) {
188-
if ($smallest-value > @!nodes[self!find-left-child($left-child)]) {
217+
if ((not $smallest-value.defined) or $smallest-value minmaxheap-cmp @!nodes[self!find-left-child($left-child)] == Order::More) {
189218
$smallest-value = @!nodes[self!find-left-child($left-child)];
190219
$smallest-index = self!find-left-child($left-child);
191220
$is-child = False;
192221
}
193222
}
194223
if (self!has-right-child($left-child)) {
195-
if ($smallest-value > @!nodes[self!find-right-child($left-child)]) {
224+
if ((not $smallest-value.defined) or $smallest-value minmaxheap-cmp @!nodes[self!find-right-child($left-child)] == Order::More) {
196225
$smallest-value = @!nodes[self!find-right-child($left-child)];
197226
$smallest-index = self!find-right-child($left-child);
198227
$is-child = False;
199228
}
200229
}
201230
}
202231
if (self!has-right-child($index)) {
203-
my $right-child;
204-
if ($smallest-value > @!nodes[($right-child = self!find-right-child($index))]) {
232+
my $right-child = self!find-right-child($index);
233+
if ((not $smallest-value.defined) or $smallest-value minmaxheap-cmp @!nodes[$right-child] == Order::More) {
205234
$smallest-value = @!nodes[$right-child];
206235
$smallest-index = $right-child;
207236
$is-child = True;
208237
}
209238

210239
if (self!has-left-child($right-child)) {
211-
if ($smallest-value > @!nodes[self!find-left-child($right-child)]) {
240+
if ((not $smallest-value.defined) or $smallest-value minmaxheap-cmp @!nodes[self!find-left-child($right-child)] == Order::More) {
212241
$smallest-value = @!nodes[self!find-left-child($right-child)];
213242
$smallest-index = self!find-left-child($right-child);
214243
$is-child = False;
215244
}
216245
}
217246
if (self!has-right-child($right-child)) {
218-
if ($smallest-value > @!nodes[self!find-right-child($right-child)]) {
247+
if ((not $smallest-value.defined) or $smallest-value minmaxheap-cmp @!nodes[self!find-right-child($right-child)] == Order::More) {
219248
$smallest-value = @!nodes[self!find-right-child($right-child)];
220249
$smallest-index = self!find-right-child($right-child);
221250
$is-child = False;
@@ -228,50 +257,50 @@ method !find-smallest(Int:D $index) {
228257

229258
method !find-largest(Int:D $index) {
230259
my ($largest-value, $largest-index, $is-child);
231-
$largest-value = -Inf;
260+
$largest-value = Any;
232261
$largest-index = $index;
233262
$is-child = False;
234263

235264
if (self!has-left-child($index)) {
236-
my $left-child;
237-
if ($largest-value < @!nodes[($left-child = self!find-left-child($index))]) {
265+
my $left-child = self!find-left-child($index);
266+
if ((not $largest-value.defined) or $largest-value minmaxheap-cmp @!nodes[$left-child] == Order::Less) {
238267
$largest-value = @!nodes[$left-child];
239268
$largest-index = $left-child;
240269
$is-child = True;
241270
}
242271

243272
if (self!has-left-child($left-child)) {
244-
if ($largest-value < @!nodes[self!find-left-child($left-child)]) {
273+
if ((not $largest-value.defined) or $largest-value minmaxheap-cmp @!nodes[self!find-left-child($left-child)] == Order::Less) {
245274
$largest-value = @!nodes[self!find-left-child($left-child)];
246275
$largest-index = self!find-left-child($left-child);
247276
$is-child = False;
248277
}
249278
}
250279
if (self!has-right-child($left-child)) {
251-
if ($largest-value < @!nodes[self!find-right-child($left-child)]) {
280+
if ((not $largest-value.defined) or $largest-value minmaxheap-cmp @!nodes[self!find-right-child($left-child)] == Order::Less) {
252281
$largest-value = @!nodes[self!find-right-child($left-child)];
253282
$largest-index = self!find-right-child($left-child);
254283
$is-child = False;
255284
}
256285
}
257286
}
258287
if (self!has-right-child($index)) {
259-
my $right-child;
260-
if ($largest-value < @!nodes[($right-child = self!find-right-child($index))]) {
288+
my $right-child = self!find-right-child($index);
289+
if ((not $largest-value.defined) or $largest-value minmaxheap-cmp @!nodes[$right-child] == Order::Less) {
261290
$largest-value = @!nodes[$right-child];
262291
$largest-index = $right-child;
263292
$is-child = True;
264293
}
265294

266295
if (self!has-left-child($right-child)) {
267-
if ($largest-value < @!nodes[self!find-left-child($right-child)]) {
296+
if ((not $largest-value.defined) or $largest-value minmaxheap-cmp @!nodes[self!find-left-child($right-child)] == Order::Less) {
268297
$largest-value = @!nodes[self!find-left-child($right-child)];
269298
$largest-index = self!find-left-child($right-child);
270299
$is-child = False;
271300
}
272301
}
273302
if (self!has-right-child($right-child)) {
274-
if ($largest-value < @!nodes[self!find-right-child($right-child)]) {
303+
if ((not $largest-value.defined) or $largest-value minmaxheap-cmp @!nodes[self!find-right-child($right-child)] == Order::Less) {
275304
$largest-value = @!nodes[self!find-right-child($right-child)];
276305
$largest-index = self!find-right-child($right-child);
277306
$is-child = False;

0 commit comments

Comments
 (0)