在Perl中实现一个节点列表

时间:2012-10-26 13:28:44

标签: perl list implementation

我编写了以下模块但不确定如何引用“last”和“head”节点。以及将下一个节点的地址存储在前一节点的“{nextNode}”中。

我试图在存储时保存类的引用,但后来它抱怨:“不是List.pm中的HASH引用”;我理解为什么但不确定语法是怎样的。

如果我取消引用$ head和$ last($$ last-> {nextNode} = \ $ class),那么我认为它正在使用我班级的实际名称;列出而不是我想要的上一个对象。

package List;

my $head = undef;
my $last = undef;

sub new {
    my $class = shift;

    # init the head of the list
    if ($head == undef) {
    $head = \$class;
    print "updated head to:$head", "\n";
    }

    $last = \$class;
    $last->{nextNode} = \$class; # update previous node to point on this new one    

    print "updated last to:$last", "\n";
    my $self = {};
    $self->{value} = shift;    
    $self->{nextNode} = ""; # reset next to nothing since this node is last

    return bless $self, $class;
}

谢谢你们

3 个答案:

答案 0 :(得分:6)

您应该将$self存储在任何地方,而不是\$class。存储$ class只是存储类的名称,而不是对象本身。

此外,对于$self->{nextNode},我会存储undef而不是空字符串。或者更好的是,根本不要创建它,并在检查它是否存在时使用exists

答案 1 :(得分:3)

你在想它。如果您使用数组作为列表而不是哈希,则无需担心 head last 。数组的头部是$array[0],最后一个成员是$array[-1]。简单易行。

这是一个用于定义列表的快速标准类定义。我只定义了一个构造函数(新的子例程)和一个方法(列表)。

package Local::List;

sub new {
   my $class = shift;

   my $self = {};
   bless $self, $class;
   $self->list([]);
}

sub list {
   my $self = shift;
   my $list_ref = shift;

   if (ref $list_ref ne "ARRAY) {
       return;
   }
   if (defined $list_ref) {
       $self->{LIST} = $list_ref;
   }
   if wantarray {
      return $self->{LIST};
   }
}

第一件事:使用其他人使用的相同标准名称。使用new作为构造函数。当我尝试查看有关如何使用您的类的文档时,我可以搜索单词 new 并知道我是如何创建类对象的。另外,使用变量名$class$self。这就是其他人所做的事情,因此很容易知道发生了什么。

注意在我的new子例程中,传递的第一个项是类的名称,而传递给我的其他子例程的第一个项是对我的类对象的引用(即$self)。这可能是最难理解的课程。

请注意new,我立即创建$self并祝福它。这样,我可以调用我的其他子程序(我的方法)为我做设置。这样,我的构造函数不知道我的类是如何构造的。这有很多好处:

  • 当我(不是)修改我的类时,我不必修改构造函数。
  • 我的构造函数始终与我的所有方法同步。
  • 当我开始定义类时,我不必知道我的类对象是如何构造的。我可以开始写我的课程,而不必担心所有关于它如何工作的肮脏细节。

请注意,list子例程(或方法)可以设置列表或返回列表。如果使用相同的子例程来设置或获取值,则会容易得多。同样在方法子例程中,当方法函数返回错误时使用空白返回。否则,总是返回一些东西。这样可以很容易地测试方法是否失败。

让我们看看你可能想要的其他一些方法。让我们拥有所有四个标准列表函数:

  • 弹出
  • 不印字

以下是一个例子:

sub push {
    my $self = shift;
    my $member = shift;

    if (not defined $member) {
        return;
    }

    my $list_ref = $self->list;
    my $return = push @{ $list_ref }, $member;
    $self->list($list_ref);

    return $return;
}
哇,这很简单。请注意,pop不知道我的班级是什么样的。它使用list方法检索列表引用。然后,它使用内置push方法将成员推送到列表中。我保存了那个返回值,这就是我要归还的东西。我甚至不确定push返回什么。我所知道的是,如果成功,push会返回某些东西。 (是的,我知道它会返回列表中的项目数。)

其他三个功能或多或少相同。这里还有一些:

  • 电流
  • 剪接
  • 最后

当前所需要做的就是存储当前值。使用相同的函数来设置和获取值。请注意,我的list方法或我的push方法或我的new构造函数知道或关心如何存储它。也不是我们的nextprevious方法。他们需要做的就是增加或减少current的值,并使用current方法子例程将其存储回来:

sub next {
   my $self = shift

   my @list = $self->list;  #Returns a list;
   my $current = $self->current;
   my $list_size = $#list;

   if ($current eq $list_size) {
      return;   #Can't return a value after the end of the list!
   }

   $current++;  #Increment the value;
   my $value = $list[$current];  #I'll return this
   $self->current($current) #Store the new current
   return $value;
}

现在,根据您的问题:获取列表的最后和头部值。这是最后一次

sub last {
   my $self = shift;

   my $list_ref = $self->list;
   return ${ $list_ref }[-1];
}

快速复制和粘贴会让我头脑发热:

sub head {
   my $self = shift;

   my $list_ref = $self->list;
   return ${ $list_ref }[0];
}

就是这样!所有令你担心的事情都是徒劳无功。

对不起,很长的帖子。我只想强调Perl中的面向对象编程并不是那么棘手,只要你遵循一些简单的指导方针即可。

(简单?use Moose;怎么样?不,我说简单!)。 ; - )

答案 2 :(得分:0)

我只想发布我的最终工作版本以备记录和您的反馈/意见。 再次感谢!!

package List;

my $head = undef;
my $last = undef;

sub new {
    my ($class, $val) = @_;
    my $self = {};

    # init the head of the list
    if (!defined $head) {
    $head = $self;
    print "updated the head of the list ($head)" . "\n";
    }
    else {
    $last->{nextNode} = $self; # update previous node to point on this new one
    }

    $last = $self; # this object is now the last one

    $self->{value} = $val; # store the value
    $self->{nextNode} = undef; # reset next to nothing since this node is last

    return bless $self, $class;
}

sub setVal {
    my ($class, $val) = @_;
    $class->{value} = $val;
}

sub getVal {
    my $class = shift;
    print $class->{value};
}

sub getNext {
    my $class = shift;
    return $class->{nextNode};
}

# return true if this is the last node, otherwise false.
sub isLast {
    my $class = shift;
    return 1 if !defined $class->{nextNode};
    return 0;
}

sub getLast {
    return $last;
}

sub getHead {
    return $head;
}

# looping through all the list and printing the values
sub showList {
    my $node = $head; # set temp node to the head

    while ( !$node->isLast() ) {
    print $node->{value} . "\n";
    $node = $node->{nextNode};
    }

    # printing last value. (should be defined but I check it just in case)
    print $node->{value} . " (last)\n" if defined $node->{value};
}

1;

脚本:

my $n0 = new List(4);
my $n1 = new List(8);
my $n2 = new List(9);
my $n3 = new List(3);
my $n4 = new List(1);
my $n5 = new List(0);
my $n6 = new List(5);
print "\nShow list: \n";
$n2->showList(); # any object will print the list