如果我尝试以下代码
#!/usr/bin/env perl use Tree::Simple; # Tree: # a # _________ | ________ # / | \ # b c d # / \ # e f # \ # g # my $tree = Tree::Simple->new('a',Tree::Simple->ROOT); $tree->addChildren( Tree::Simple->new('b'),Tree::Simple->new('c'),Tree::Simple->new('d'),); $tree->getChild(1)->addChildren ( Tree::Simple->new('e'),Tree::Simple->new('f'),); $tree->getChild(1)->getChild(1)->addChildren ( Tree::Simple->new('g'),); $trav_func= sub { my $node = shift; printf "node : %s leaf : %3s root : %s\n",$node->getNodeValue,$node->isLeaf ? 'yes' : 'no',$node->isRoot ? 'yes' : 'no'; }; # traversal does not report the root - error ? print "------ preorder : traverse( \$trav_func ) \n"; $tree->traverse( $trav_func ); print "\n"; print "------ postorder : traverse( sub{},\$trav_func ) \n"; $tree->traverse( sub{},$trav_func ); print "\n";
输出是
------ preorder : traverse( $trav_func ) node : b leaf : yes root : no node : c leaf : no root : no node : e leaf : yes root : no node : f leaf : no root : no node : g leaf : yes root : no node : d leaf : yes root : no ------ postorder : traverse( sub{},$trav_func ) node : b leaf : yes root : no node : e leaf : yes root : no node : g leaf : yes root : no node : f leaf : no root : no node : c leaf : no root : no node : d leaf : yes root : no
显示未访问root“a”.我对树遍历的理解是应该访问所有节点.我错了还是在某些情况下有理由不访问root?
附录:
Tree :: Simple :: traverse()实现为:
sub traverse { my ($self,$func,$post) = @_; # ... some checks here not shown foreach my $child ($self->getAllChildren()) { $func->($child); $child->traverse($func,$post); defined($post) && $post->($child); } }
对于第一个节点(root),没有调用$func / $post,因此没有访问它.
如果使用覆盖traverse()
package My::Tree::Simple; use parent 'Tree::Simple'; # the original code of Tree::Simple::traverse() # but $func() and $post() outside of foreach-loop # allowing the root to be visited sub my_traverse { my ($self,$post) = @_; (defined($func)) || die "Insufficient Arguments : Cannot traverse without traversal function"; (ref($func) eq "CODE") || die "Incorrect Object Type : traversal function is not a function"; (ref($post) eq "CODE") || die "Incorrect Object Type : post traversal function is not a function" if defined($post); $func->($self); # put outside of foreach foreach my $child ($self->getAllChildren()) { $child->my_traverse($func,$post); } defined($post) && $post->($self); # put outside of foreach }
它像我预期的那样工作.
解决方法
我最近一直在使用Tree :: Simple包,我认为观察到的行为与文档一致.例如,考虑’getDepth’函数.在文档中它说:
getDepth
Returns a number representing the invocant’s depth within the
hierarchy of Tree::Simple objects.NOTE: A ROOT tree has the depth of -1. This be because Tree::Simple
assumes that a tree’s root will usually not contain data,but just be
an anchor for the data-containing branches. This may not be intuitive
in all cases,so I mention it here.
从这一点来看,在我看来,你需要并且“锚定”不得包含数据.换句话说,您的树应该如下所示:
# Tree: # anchor # | # a # _________ | ________ # / | \ # b c d # / \ # e f # \ # g #
然后,’anchor’将是深度-1,’a’将是深度0,’b’,’c’,’d’将是深度1.
希望这可以帮助.