punitpawar has asked for the wisdom of the Perl Monks concerning the following question:

Hello , I am struggling to write code to implement a doubly link list. Could any of you please help me with it. This is what I have written so far. If you could point me to any material which shows how a doubly linked list is implemented in PErl that will be of great help to me...
#!/usr/bin/perl use strict; use warnings; use Data::Dumper; my $head= undef; ## reference to first node my $tail=\$head; ## reference to the "next" field of the last node my $list; open FILE, "<datastored.txt" or die $!; # Creating a doubly linked list while (<FILE>){ my $node = { "data" => $_ , "next" => undef, "prev" => undef, }; $$tail=$node; $node->{"prev"}= $tail; $tail = \$node->{"next"}; } print Dumper $head; &print_list($head); sub print_list { $list=$_[0]; while ($list) { print Dumper $list; print "$list->{data}"; $list = $list->{next}; } }

Replies are listed 'Best First'.
Re: Doubly link list implementation
by Anonymous Monk on Nov 24, 2015 at 19:51 UTC
Re: Doubly link list implementation
by BrowserUk (Patriarch) on Nov 24, 2015 at 19:37 UTC

    In general, it is almost never necessary and always inefficient to use linked lists (single or double) in Perl.

    If you describe the application -- ie. why you think you need a double linked list -- we will probably be able to show you a better, more efficient way of solving the problem.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority". I knew I was on the right track :)
    In the absence of evidence, opinion is indistinguishable from prejudice.

      Seems like homework.

Re: Doubly link list implementation
by Laurent_R (Canon) on Nov 24, 2015 at 22:36 UTC
    As aptly said by BrowserUk and other monks, it is almost never necessary to use linked lists in Perl. And, as illustrated by GotToBTru, a simple array can do it just as well in Perl (because it is so easy in Perl to add or remove items anywhere in the array).

    However, this is your code quickly modified to make a doubly-linkled list in the old fashion (I leave out the tail as an exercise):

    #!/usr/bin/perl use strict; use warnings; my $head = {data => 0, prev => undef, next => undef}; my $previous = $head; while (<DATA>){ chomp; $previous->{next} = { "data" => $_ , "next" => undef, "prev" => $previous, }; $previous = $previous->{next}; } my $curr = $head; while (1) { last unless defined $curr->{next}; print "Current: ", $curr->{data}, "\tPrevious: ", $curr->{prev}{data} // "", "\tNext: ", $curr->{next}{data} // "", "\n"; $curr = $curr->{next}; } __DATA__ 1 2 3 4 5
    This prints the values of the items in the list:
    $ perl doubly_linked.pl Current: 0 Previous: Next: 1 Current: 1 Previous: 0 Next: 2 Current: 2 Previous: 1 Next: 3 Current: 3 Previous: 2 Next: 4 Current: 4 Previous: 3 Next: 5
    And this is a Data Dumper view of the structure:
      Hello, Thanks so much for the help. I was trying to study doubly linked list and was struggling with its understanding. Thanks again.
        Hello, I do have a follow up question regarding node insertion in doubly linked list. so my intent is to insert a node after the head node and before the last node.
        Although I am able to do the insert correctly , when I try to print the output starting from the head . I do not see node that I had inserted before the tail node.
        Similarly when I print the output starting from the tail node , I do not see node that I inserted after the head node.

        Observe the values printed in the "current" field from my output.

        Any corrections/ suggestions which you can provide will be very helpful

        here is my code
        #!/usr/bin/perl use strict; use warnings; my $head = {data => 0, prev => undef, next => undef}; my $previous = $head; open FILE, "<datastored.txt" or die $!; while (<FILE>){ chomp; $previous->{next} = { "data" => $_ , "next" => undef, "prev" => $previous, }; $previous = $previous->{next}; } ### Inserting element at the beginning of the list after the head node my $curr = $head; $curr->{next}= { "data" => 30, "next" => $curr->{next}, "prev" => $curr, }; ### Inserting element at the end of the list before the tail node $curr = $previous; $curr->{prev}= { "data" => 40, "next" => $curr, "prev" => $curr->{prev}, }; ## Printing from head print "printing from head \n"; $curr = $head; while (1) { last unless defined $curr->{next}; print "Current: ", $curr->{data}, "\tPrevious: ", $curr->{prev}{data} // "", "\tNext: ", $curr->{next}{data} // "", "\n"; $curr = $curr->{next}; } ## printing from tail print "Printing From tail \n"; while (1) { last unless defined $curr->{prev}; print "Current: ", $curr->{data}, "\tPrevious: ", $curr->{prev}{data} // "", "\tNext: ", $curr->{next}{data} // "", "\n"; $curr = $curr->{prev}; }
        Output form this program
        printing from head Current: 0 Previous: Next: 30 Current: 30 Previous: 0 Next: line1 Current: line1 Previous: 0 Next: line2 Current: line2 Previous: line1 Next: line3 Current: line3 Previous: line2 Next: line4 Current: line4 Previous: line3 Next: line5 Printing From tail Current: line5 Previous: 40 Next: Current: 40 Previous: line4 Next: line5 Current: line4 Previous: line3 Next: line5 Current: line3 Previous: line2 Next: line4 Current: line2 Previous: line1 Next: line3 Current: line1 Previous: 0 Next: line2 Current: 0 Previous: Next: 30
        content of datastored.txt
        line1 line2 line3 line4 line5
      Hello, Thanks so much for the help. I was trying to study doubly linked list and was struggling with its understanding. Thanks again.
Re: Doubly link list implementation
by GotToBTru (Prior) on Nov 24, 2015 at 21:20 UTC

    This was a useful exercise in Pascal or C to learn how to use pointers. Helped with conceptualizing them, and also taught a thing or three about how to turn a description into an algorithm, handling end cases and always being aware of the actual contents of a variable, which are useful in programming in general.

    But if I really need to keep track of what proceeds and what follows, I choose to avoid references/pointers as needlessly complex.

    use strict; use warnings; my @list; # Creating a doubly linked list while (<DATA>){ push @list, $_ } chomp @list; &print_list(); sub print_list { my $format = "%5s -> %5s -> %5s\n"; printf $format,'prev','data','next'; for (my $i=0; $i<$#list; $i++) { printf $format, $i>0 ? $list[$i-1] : 'undef', $list[$i], $i < $#list - 1 ? $list[$i+1] : 'undef' } } __DATA__ the quick brown fox jumps over the lazy dog

    Output:

    prev -> data -> next undef -> the -> quick the -> quick -> brown quick -> brown -> fox brown -> fox -> jumps fox -> jumps -> over jumps -> over -> the over -> the -> lazy the -> lazy -> dog lazy -> dog -> undef
    Dum Spiro Spero
Re: Doubly link list implementation
by Lennotoecom (Pilgrim) on Nov 24, 2015 at 20:45 UTC
    a($_) while <DATA>; for (sort keys %h){ print "$_: my address is $h{$_}\n"; print "last: $h{$_}{'a'} >>> $h{$_}{'a'}{'c'}\n"; print "next: $h{$_}{'b'} >>> $h{$_}{'b'}{'c'}\n\n"; } sub a { chomp; $t = shift; $h{$t}{'a'} = $l; $h{$t}{'c'} = $t; $$l{'b'} = $h{$t}; $l = $h{$t}; } __DATA__ a b c d e

    output
    a: my address is HASH(0x2b230) last: >>> next: HASH(0x22e44e8) >>> b b: my address is HASH(0x22e44e8) last: HASH(0x2b230) >>> a next: HASH(0x22e45d8) >>> c c: my address is HASH(0x22e45d8) last: HASH(0x22e44e8) >>> b next: HASH(0x22ef2a0) >>> d d: my address is HASH(0x22ef2a0) last: HASH(0x22e45d8) >>> c next: HASH(0x22ef468) >>> e e: my address is HASH(0x22ef468) last: HASH(0x22ef2a0) >>> d next: >>>
Re: Doubly link list implementation
by muba (Priest) on Nov 24, 2015 at 21:08 UTC

    As other, wiser monks than me have already pointed out, it's hardly needed or advisable or even desirable in Perl. But if you must...

    A web search woulda gotten you there, too.

      Thanks for the link. I did not want to use a module , but I wanted to understand the algorithmic approach of doing this in perl. Perl is the only language I know well , so this was my only resort...
        If you are interested in how the module does it, you can always look at the source on CPAN or on METACPAN.
        (In the general case, you search for the module on or , and they have a "Source" link.)
Re: Doubly link list implementation
by stevieb (Canon) on Nov 24, 2015 at 19:30 UTC

    Hi punitpawar,

    Could you please provide us with a sample of your datastored.txt input file, and if possible, what your expected output looks like?

      datastored.txt just contains
      line1 line2 line3 line4
      The expected output I was trying to achieve was , I should be able to print the elements of the list in reverse order If I began from the tail and in forward order if I began from the head ....