11use v6 ;
22unit class Algorithm::MinMaxHeap ;
33
4+ use Algorithm::MinMaxHeap::Comparable;
5+ use Algorithm::MinMaxHeap::CmpOperator;
6+
47has @ . 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+
83112method is-empty () returns Bool : D {
84113 return @ ! nodes . elems == 0 ?? True !! False ;
85114}
86115
87116method ! 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
105134method ! 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
114143method ! 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
173202method ! 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
229258method ! 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