Data-CircularList

 view release on metacpan or  search on metacpan

lib/Data/CircularList.pm  view on Meta::CPAN

    
    # you can also use strings as cells
    $list = Data::CircularList->new;
    $list->insert('steeve');
    $list->insert('hisashi');
    $list->insert('takairo');
    $list->insert('kazuyo');
    $list->insert('jane');
    
    # display
    $iter = $list->iterator;
    while ($iter->has_next) {
       print $iter->next->data . "\n";
    }
    # you can see result sorted
    # hisashi
    # jane
    # kazuyo
    # steeve
    # takahiro
    # hisashi  <= 1st value is displayed
    # jane        eternal loop
    ...

    # display
    $iter = $list->iterator( rotate => 2 );
    while ($iter->has_next) {
       print $iter->next->data . "\n";
    }
    # you can see result sorted
    # hisashi
    # jane
    # kazuyo
    # steeve
    # takahiro
    # hisashi
    # jane
    # kazuyo
    # steeve
    # takahiro <= end. $iter->has_next return true until second rotation completed.

    # you can also use some object as cells
    $list = Data::CircularList->new;
    $list->insert(Person->new(name => 'lally'));
    $list->insert(Person->new(name => 'hisashi'));
    $list->insert(Person->new(name => 'takairo'));
    $list->insert(Person->new(name => 'kazuyo'));
    $list->insert(Person->new(name => 'jane'));
    
    # you have to implements compare_to method in you object.
    # you have to write sort logic in compare_to method.
    package Person;

    sub new {
        my $class = shift;
        my %args = @_;
        my $self = {
            name => $args{'name'},
            length => length($args{'name'}),
        };
        bless $self => $class;
        $self->length(length($args{'name'}));
        return $self;
    }

    # sort by length of name, and name
    sub compare_to {
        my $self = shift;
        my $cell = shift;

        if ($self->length > $cell->length) {
            return 1;
        } elsif ($self->length == $cell->length) {
            return $self->name gt $cell->name ? 1 : 0;
        } else {
            return 0;
        }
    }

    sub name {
        my $self = shift;
        return defined $self->{'name'} ? $self->{'name'} : undef;
    }

    sub length {
        my $self = shift;
        return defined $self->{'length'} ? $self->{'length'} : undef;
    }

=head1 SUBROUTINES/METHODS

=head2 new

constructor. Any arguments don't require.

=cut

sub new {
    my $class = shift;
    my $self = {};
    $self->{'header'} = Data::CircularList::Cell->new("!!Circular List Header!"),
    $self->{'header'}->next($self->{'header'}),
    bless $self => $class;
    return $self;
}

=head2 insert($cell)

insert a cell on the circular linked list.
You can see SYNOPSIS as a example.

=cut

sub insert {
    my $self = shift;
    my $cell = shift;
    $cell = Data::CircularList::Cell->new($cell);

    my $p = $self->header->next;
    my $q = $self->header;

    if ($p ne $q) {
        while (defined($p) && $p->can('data') && $cell->compare_to($p->data) > 0) {
            $q = $p;
            $p = $p->next;
            last if !blessed($p->data);
        }
    }

    my $new_cell = Data::CircularList::Cell->new($cell);
    $new_cell->next($p);
    $q->next($new_cell);
}

=head2 iterator

get a iterator to traverse the circular linked list.
You can see SYNOPSIS as a example.

=cut

sub iterator {
    my $self = shift;
    my %args = @_;
    my $rotate = defined $args{'rotate'} ? $args{'rotate'} : undef;
    my $iter = Data::CircularList::Iterator->new($self, $rotate);
    return $iter;
}

# free memory of cicular data
sub DESTROY {
    my $self = shift;
    delete $self->{'header'};
    if (DEBUG) {
        carp "destroying $self\n";
    }
}

=head1 AUTHOR

shinchit, C<< <shinchi.xx at gmail.com> >>

=head1 BUGS

 view all matches for this distribution
 view release on metacpan -  search on metacpan

( run in 1.022 second using v1.00-cache-2.02-grep-82fe00e-cpan-1925d2aa809 )