我需要遍历二叉树。树的值位于散列中。
我使用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' } ";
答案 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};
}