Home > Net >  Array::Heap using custom comparison function
Array::Heap using custom comparison function

Time:09-17

I was experimenting with Array::Heap module and wanted to create a heap sorted in reverse order. So I created this code:

#!/usr/bin/perl

use utf8;
use strict;
use warnings;
use Array::Heap;

my @heap;
make_heap_cmp {$b <=> $a} @heap;
push_heap_cmp {$b <=> $a} @heap, 4;
push_heap_cmp {$b <=> $a} @heap, 1;
push_heap_cmp {$b <=> $a} @heap, 5;
push_heap_cmp {$b <=> $a} @heap, 7;
push_heap_cmp {$b <=> $a} @heap, 2;

while (my $val = pop_heap_cmp {$b <=> $a} @heap)
{
    print "$val\n";
}

It is correct, it outputs 7, 5, 4, 2, 1.

But the code looks ugly: I repeated the comparison function for every single call. Unfortunately, module docs lack examples of use cases for special comparison function. Can somebody tell me, whether it's possible to improve this code or suggest a better module, implementing heaps?

CodePudding user response:

Put your code in a loop:

my @heap;

for my $i (4, 1, 5, 7, 2) {
  push_heap_cmp {$b <=> $a} @heap, $i;
}

Or hide the complexity away in a subroutine;

sub add_to_heap {
   my ($heap, $add) = @_;

   push_heap_cmp { $b <=> $a } @$heap, $add;
}

my @heap;

for my $i (4, 1, 5, 7, 2) {
  add_to_heap \@head, $i;
}

CodePudding user response:

That's what subs are for.

my $rev = sub { $b <=> $a };

sub make_heap_rev(\@)  { &make_heap_cmp($rev, @_) }
sub push_heap_rev(\@@) { &push_heap_cmp($rev, @_) }
sub pop_heap_rev(\@)   { &pop_heap_cmp($rev, @_) }

Then you can use

my @heap = ( 4, 1, 5, 7, 2 );
make_heap_rev @heap;
while (my $val = pop_heap_rev @heap) {
   say $val;
}

or

my @heap;
push_heap_rev @heap, 4, 1, 5, 7, 2;
while (my $val = pop_heap_rev @heap) {
   say $val;
}
  • Related