Hash-PriorityQueue

 view release on metacpan or  search on metacpan

lib/Hash/PriorityQueue.pm  view on Meta::CPAN

package Hash::PriorityQueue;

our $VERSION = '0.01';

use strict;
use warnings;

use List::Util qw(min);

sub new {
	return bless {
		queue => {},     # payloads by prio
		prios => {},     # prios by payload
		min_key => undef,
	}, shift();
}

sub delete {
	my ($self, $payload) = @_;
	my $op = $self->{prios}->{$payload};
	if (defined($op)) {
		$self->{queue}->{$op} = [ grep { $_ ne $payload } @{$self->{queue}->{$op}} ];
		if (!@{$self->{queue}->{$op}}) {
			delete($self->{queue}->{$op});
			if ($self->{min_key} == $op) {
				$self->{min_key} = min keys(%{$self->{queue}});
			}
		}
	}
}

sub pop {
	my ($self) = @_;
	if (!defined($self->{min_key})) {
		return undef;
	}

	my $elem = shift(@{$self->{queue}->{$self->{min_key}}});
	if (!@{$self->{queue}->{$self->{min_key}}}) {
		delete($self->{queue}->{$self->{min_key}});
		$self->{min_key} = min keys(%{$self->{queue}});
	}
	delete($self->{prios}->{$elem});
	return $elem;
}

sub update {
	my ($self, $payload, $priority) = @_;
	my $op = $self->{prios}->{$payload};
	if (defined($op)) {
		$self->{queue}->{$op} = [ grep { $_ ne $payload } @{$self->{queue}->{$op}} ];
		if (!@{$self->{queue}->{$op}}) {
			delete($self->{queue}->{$op});
		}
	}

	$self->{prios}->{$payload} = $priority;
	push(@{$self->{queue}->{$priority}}, $payload);
	if (!defined($self->{min_key}) or $priority < $self->{min_key}) {
		$self->{min_key} = $priority;
	} elsif ($priority > $self->{min_key} and (defined($op) and !defined($self->{queue}->{$op}))) {
		$self->{min_key} = min keys(%{$self->{queue}});
	}
}

*insert = \&update;

1;

__END__

=head1 NAME

Hash::PriorityQueue - priority queue based on perl hashes

=head1 SYNOPSIS

 my $prio = Hash::PriorityQueue->new();
 $prio->insert("foo", 2);
 $prio->insert("bar", 1);
 $prio->insert("baz", 3);
 my $next = $prio->pop(); # "bar"
 # I decided that "foo" isn't as important anymore
 $prio->update("foo", 99);

=head1 DESCRIPTION

This module implements a high-performance priority queue, based on a hash.
It's written in pure Perl.

Available functions are:

=head2 B<new>()

Obvious.

=head2 B<insert>(I<$payload>, I<$priority>)

=head2 B<update>(I<$payload>, I<$new_priority>)

Adds the specified payload (anything fitting into a scalar) to the priority
queue, using the specified priority. Smaller means more important.

If the item already exists in the queue, it is assigned the new priority.

These names are actually the same function. The alternative name is provided
so you can make clear which operation you intended to be executed.



( run in 0.615 second using v1.01-cache-2.11-cpan-df04353d9ac )