如何为变量分配对散列中的键的引用

时间:2013-11-17 15:21:16

标签: perl data-structures tree

我需要遍历二叉树。树的值位于散列中。

我使用Data::Dumper模块来显示哈希值,但是指针(显示我们旅行时树所在位置的变量)将不接受对树的引用。

这是我的代码的简化版

#!/usr/bin/perl
use v5.10;
use Data::Dumper;

# ID = id of the nod in the tree     
# 'v' = value of the nod  
# 'p' = id of the father nod  
# '+' = son of the nod ( bigger than father)
# '-' = son of the nod ( smaller than father)  

my $tree = {

    'id' => 0,
    'v' => 12,
    '+' => { 
            'id' => 1,
            'p' => 12,
            'v' => 18,
        }
};

my $pointer = $tree -> { '+' } -> { 'id' };      

# travel trough the tree
while(exists  ($pointer -> {'p'}))      # while $pointer will have a father
  $noeud_courant =  $noeud_courant->{'p'};  # give $pointer the value of the father i                   
}

say "value of the first father = $pointer -> { 'v' } ";

1 个答案:

答案 0 :(得分:1)

如果某个节点$n的{​​{1}}等于12,您希望能够从中找到$n->{p}等于12的节点$p。但是您的程序不包含任何可以轻松找到节点$p->{id}的内容。你需要添加它。

执行此操作的一种方法是组合将ID号映射到树节点的索引。索引只是一个数组,其中$p是ID号为$index[$n]的树节点。此函数在树的根目录上运行,为它构建索引:

$n

要使用此功能,请致电:

sub index_tree {
  my ($root, $index) = @_;
  $index->[$root->{id}] = $root;
  for my $sub_node (values %$root) {
    next unless ref $sub_node eq "HASH";
    index_tree($sub_node, $index);
  }
}

现在my @index; index_tree($tree, \@index); 是您的索引。假设您的示例中有@index,并且您想要追溯到根目录。你可以使用:

$pointer = 1

在循环的每一步中,while (defined $pointer) { my $node = $index[$pointer]; $pointer = $node->{p}; } 是当前节点的ID,$pointer是当前节点本身。

如果ID的空间稀疏,那么为索引使用哈希而不是数组是合适的。


您可以将$node条目替换为指向父节点本身的指针,而不是将索引存储在单独的数组中:

p

执行此操作后,除root之外的每个节点都将其整个父节点存储在其sub fix_parent_pointers { my ($root) = @_; for my $sub_node (values %$root) { next unless ref $sub_node eq "HASH"; $sub_node->{p} = $root; fix_parent_points($sub_node); } } fix_parent_pointers($tree); 元素中以代替ID号。如果p是一个节点,您现在可以通过执行以下操作追溯到根目录:

$node

这种技术的主要缺点是,当你完成它时,Perl将无法再对你的树进行垃圾收集。通过使用Scalar::Util::weaken()弱化父引用可以避免这种情况,因此它不会阻碍垃圾回收:

while (exists $node->{p}) {
  $node = $node->{p};
}