如何解决为什么需要显式引用属性才能修改它,而不是使用引用?
我是Perl的新手。我第一次看它是在几天前,并决定练习实现一些算法和数据结构以进行学习。在这种情况下为二叉搜索树(BST)。
当前,我使用的是Node包“ Node.pm”,BinarySearchTree包“ BST.pm”和用于使用代码“ Main.pl”的入口点。
我的问题是在使用对根属性的引用时插入树的根节点时出现的(我知道它只是哈希表中的一个键=>值,但是使用传统的OOP术语,我喜欢将其称为属性)。
这里是上下文的构造函数:
BST.pm
sub new() {
my $type = shift;
my $this = {};
my $list = shift;
$this->{'unordered_list'} = $list;
$this->{'root'} = undef;
bless($this,$type);
return $this;
}
构造函数从整数列表中构造一个二进制搜索树,直到第一次调用“插入”时,根节点才被定义。
在对“ BuildUnbalancedTree”的调用中,我传递了对“ root”属性的引用:
Main.pl
$bst = BST->new($nums);
$bst->BuildUnbalancedTree(\$bst->{'root'});
$bst->TraverseInOrder($bst->{'root'});
BST.pm
sub BuildUnbalancedTree(){
my $this = shift;
my $root = shift;
foreach my $key (@{$this->{'unordered_list'}}){
my $newnode = $this->NewNode($key);
$this->Insert($$root,$newnode);
}
}
在“插入”方法中,如果我尝试使用传递给它的变量插入根节点,则除了根节点之外,树的一部分已构建。子节点都已设置,但根节点本身的值从未设置。
这是我希望可以使用的方法,但不可行:
sub Insert(){
my $this = shift;
my $root = shift;
my $node = shift;
if(!$root) {
$root = $node;
} elsif($node->{'value'} > $root->{'value'}) {
if(!$root->{'right'}) {
$root->{'right'} = $node;
} else {
$this->Insert($root->{'right'},$node);
}
} else {
if(!$root->{'left'}){
$root->{'left'} = $node;
} else {
$this->Insert($root->{'left'},$node)
}
}
}
假设第一个条件仅在首次调用“ Insert”时成立,所以我更改了这一行:
$root = $node;
至:
$this->{'root'} = $node;
它确实有效,但是我真的很想知道为什么其他方法不够用。我相信这是因为我在调用“ BuildUnbalancedTree”时不引用根参数(如果不这样做,它会破坏所有内容),但我非常感谢您确认并可能进行一些简短的专家分析。
解决方法
您的方法Insert
应该引用根而不是值。通过执行$this->Insert($root,$newnode);
而不是$this->Insert($$root,$newnode);
进行调用,并在$root
中将$$root
的每次出现Insert
更改,并用{{1}替换递归调用}(与$this->Insert(\$$root->{'right'},$node);
相同)。
问题在于,当您执行left
时,会将根的 value 传递给$this->Insert($$root,$newnode);
。在第一次调用时,尚未定义Insert
,这意味着您将$root
传递给undef
(它存储在其本地值Insert
中)。因此,$root
仅在本地设置if (!$root) { $root = node; }
的值。
请注意,一旦将对根的引用传递给$root
(而不是值),就可以简化Insert
方法:
Insert
由于您从未使用过sub Insert {
my ($root,$node) = @_;
if(!$$root) {
$$root = $node;
} elsif($node->{'value'} > $$root->{'value'}) {
Insert(\$$root->{'right'},$node);
} else {
Insert(\$$root->{'left'},$node);
}
}
,因此已将它们从参数中删除。将此$this
称为Insert
(而不是Insert($root,$newnode);
)。
其他评论:
-
做
$this->Insert(...)
可能不是一个好主意:例如,如果这样做:my $list = shift;
您的BST现在包含
my @list = (12,5,6,19); my $bst = BST->new(\@list); push @list,42; $bst->BuildUnbalancedTree(\$bst->{'root'});
,这可能是违反直觉的。更好的方法可能是将列表(而不是数组引用)传递给构造函数:42
(请注意,我已经删除了
sub new { my $class = shift; my @content = @_; my $this = { unordered_list => \@content }; return bless($this,$class); }
:当您尝试访问它时,Perl的自动生存功能会自动创建它)。 -
您的
$this->{'root'} = undef;
方法将根作为参数,这有点令人惊讶,因为根存储在树中。我建议改为:BuildUnbalancedTree
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。