Advertisement
DRVTiny

ring_dll.pl

Jan 19th, 2018
460
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 3.17 KB | None | 0 0
  1. package Ring::DoubleLinkedList;
  2. use 5.16.1;
  3. use Scalar::Util qw(looks_like_number);
  4. use constant {
  5.     PREV_NODE => 0,
  6.     DATA_REF  => 1,
  7.     NEXT_NODE => 2,
  8. };
  9.  
  10. sub new {
  11.     my ($class, $size)=@_;
  12.     bless +{
  13.         'size'      => (looks_like_number($size) and $size>0 and int($size)==$size) ? $size : die('You must specify the size of the list and it must be natural number'),
  14.         'stackFree' => [reverse(0..($size-1))],
  15.         'indexHead' => undef,
  16.         'indexTail' => undef,
  17.         'nodes'     => [],
  18.     }, (ref($class) || $class)
  19. }
  20.  
  21. sub add {
  22.     my ($dl, $elPayLoad)=@_;
  23.     if (@{$dl->{'stackFree'}}) {
  24.         my $indexNewEl=pop($dl->{'stackFree'});
  25.         # "Next" pointer of the head node will always point to undef
  26.         # "Previous" pointer - to the index of the node which was the head before we add new element (and undef if there is only one element in the list)
  27.         $dl->{'nodes'}[$indexNewEl] = [$dl->{'indexHead'}, \$elPayLoad, undef];
  28.         if (defined $dl->{'indexHead'}) {
  29.             $dl->{'nodes'}[$dl->{'indexHead'}][NEXT_NODE]=$indexNewEl
  30.         } else {
  31.             $dl->{'indexTail'}=$indexNewEl
  32.         }
  33.         $dl->{'indexHead'}=$indexNewEl
  34.     } else {
  35.         my $nodeOldTailNewHead=$dl->{'nodes'}[$dl->{'indexTail'}];
  36.         $dl->{'indexHead'}=$dl->{'nodes'}[
  37.             $nodeOldTailNewHead->[PREV_NODE]=$dl->{'indexHead'}
  38.         ][NEXT_NODE]=$dl->{'indexTail'};
  39.        
  40.         $nodeOldTailNewHead->[DATA_REF]=\$elPayLoad;
  41.  
  42.         undef $dl->{'nodes'}[
  43.             $dl->{'indexTail'}=$nodeOldTailNewHead->[NEXT_NODE]
  44.         ][PREV_NODE];
  45.         undef $nodeOldTailNewHead->[NEXT_NODE];
  46.     }
  47. }
  48.  
  49. sub del {
  50.     my ($dl, $node)=@_;
  51.     my ($prv, $nxt)=@{$node}[PREV_NODE,NEXT_NODE];
  52.     my $indexSelf;
  53.     if (defined $prv) {
  54.         $indexSelf=$dl->{'nodes'}[$prv][NEXT_NODE];
  55.         $dl->{'nodes'}[$prv][NEXT_NODE]=$nxt
  56.     } else {
  57.         $dl->{'indexTail'}=$nxt
  58.     }
  59.    
  60.     if (defined $nxt) {
  61.         $indexSelf=$dl->{'nodes'}[$nxt][PREV_NODE] unless defined $indexSelf;
  62.         $dl->{'nodes'}[$nxt][PREV_NODE]=$prv
  63.     } else {
  64.         $dl->{'indexHead'}=$prv
  65.     }
  66.     if (defined $indexSelf) {
  67.         push @{$dl->{'stackFree'}}, $indexSelf
  68.     } else {
  69.         $dl->reset
  70.     }
  71.     undef $node;
  72. }
  73.  
  74. sub reset {
  75.     @{$_[0]}{qw/stackFree nodes indexHead indexTail/}=(
  76.         [reverse(0..$_[0]->{'size'})],  # stackFree ()<-
  77.         [],                             # nodes ->()
  78.         undef,                          # ->head
  79.         undef                           # ->tail
  80.     )
  81. }
  82.  
  83. use Data::Dumper;
  84. sub dump {
  85.     my $dl=$_[0];
  86.     print Dumper $dl;
  87.     return unless defined $dl->{'indexTail'};
  88.     my $node=$dl->{'nodes'}[$dl->{'indexTail'}];
  89.     do {
  90.         printf("<-(%s) || %s || (%s)->\n", $node->[PREV_NODE]//'nil', ${$node->[DATA_REF]}, $node->[NEXT_NODE]//'nil');
  91.     } while defined($node->[NEXT_NODE]) and $node=$dl->{'nodes'}[$node->[NEXT_NODE]];
  92. }
  93.  
  94. 1;
  95.  
  96. package main;
  97. print 'nElements='; my $n=<STDIN>; chomp;
  98. my $rdll=Ring::DoubleLinkedList->new($n);
  99. while (<STDIN>) {
  100.     chomp;
  101.     exit if $_ eq 'exit';
  102.     $rdll->add($_);
  103.     $rdll->dump;
  104. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement