我有一个代码试图找到Eulerian path这样的代码。但不知怎的,它不起作用。 代码有什么问题?
use strict;
use warnings;
use Data::Dumper;
use Carp;
my %graphs = ( 1 => [2,3], 2 => [1,3,4,5], 3 =>[1,2,4,5], 4 => [2,3,5], 5 => [2,3,4]);
my @path = eulerPath(%graphs);
sub eulerPath {
my %graph = @_;
# count the number of vertices with odd degree
my @odd = ();
foreach my $vert ( sort keys %graph ) {
my @edg = @{ $graph{$vert} };
my $size = scalar(@edg);
if ( $size % 2 != 0 ) {
push @odd, $vert;
}
}
push @odd, ( keys %graph )[0];
if ( scalar(@odd) > 3 ) {
return "None";
}
my @stack = ( $odd[0] );
my @path = ();
while (@stack) {
my $v = $stack[-1];
if ( $graph{$v} ) {
my $u = ( @{ $graph{$v} } )[0];
push @stack, $u;
# Find index of vertice v in graph{$u}
my @graphu = @{ $graph{$u} }; # This is line 54.
my ($index) = grep $graphu[$_] eq $v, 0 .. $#graphu;
delete @{ $graph{$u} }[$index];
delete @{ $graph{$v} }[0];
}
else {
push @path, pop(@stack);
}
}
print Dumper \@path;
return @path;
}
我得到的错误是:
Use of uninitialized value in hash element at euler.pl line 54
我希望它能像这样返回输出:
$VAR = [5, 4, 3, 5, 2, 3, 1, 2, 4];
实际上我试图模仿Python中的工作代码:
def eulerPath(graph):
# counting the number of vertices with odd degree
odd = [ x for x in graph.keys() if len(graph[x])&1 ]
print odd
odd.append( graph.keys()[0] )
if len(odd) > 3:
return None
stack = [ odd[0] ]
path = []
# main algorithm
while stack:
v = stack[-1]
if graph[v]:
u = graph[v][0]
stack.append(u)
# deleting edge u-v
#print graph[u][ graph[u].index(v) ]
#print graph[u].index(v)
del graph[u][ graph[u].index(v) ]
del graph[v][0]
else:
path.append( stack.pop() )
return path
stack_ = eulerPath({ 1:[2,3], 2:[1,3,4,5], 3:[1,2,4,5], 4:[2,3,5], 5:[2,3,4] })
print stack_
答案 0 :(得分:1)
在Perl中,delete
不会重新编制索引。从Perl documentation:
delete()也可用于数组和数组切片,但其行为不那么简单。虽然exists()将为已删除的条目返回false,但删除数组元素永远不会更改现有值的索引;使用shift()或splice()。
如文档中所述,您可以使用splice
删除&重新索引。
my @graphu = @{ $graph{$u} }; # This is line 54.
my ($index) = grep $graphu[$_] eq $v, 0 .. $#graphu;
splice @{ $graph{$u} }, $index, 1;
splice @{ $graph{$v} }, 0, 1;
除此之外,测试是否存在任何未经编辑的路径存在问题:
my $v = $stack[-1];
if ( $graph{$v} ) {
my $u = ( @{ $graph{$v} } )[0];
Perl和Python之间的一个区别是Perl让你处理解除引用。 $graph{$v}
最初包含数组引用;只要它继续引用数组,表达式为true,此测试将始终成功。在相应的Python语句(if graph[v]:
)中,它是被评估的graph[v]
(列表)的值。尝试:
my $v = $stack[-1];
if ( @{$graph{$v}} ) {
my $u = ( @{ $graph{$v} } )[0];
我不打算在这里给出Perl调试的基础知识(因为someone already did是Perl文档的一部分,laziness可能是一件好事),但是顺序简要介绍一下。调试的本质是在程序运行时检查数据(也称为“程序状态”)。您可以使用脚手架在程序中的各个点打印出数据(转储器对此很有用),或者使用交互式调试器来逐步执行该程序。交互式调试器是首选,因为它们为您提供更多控制并且通常更快(如果您没有在脚手架代码中打印出关键数据,则需要重新启动程序;使用调试器时,无需重新启动) 。
使用这两种技术,检查eulerPath
子例程中的变量:@graph
,@stack
,$v
,$u
。使用原始程序,用delete
替换splice
的中间程序,以及制作所有建议更改的程序执行此操作。看看你是否可以从数据中找出出错的地方并产生错误,然后导致我建议的更改。
答案 1 :(得分:1)
我尝试过Outis的suggestion,它按照Neversaint的要求运行:)
wget的
http://misccb.googlecode.com/git-history/a4c46aaecbda3c103b92d0152fa2cdbdf4da4ea0/euler.pl
perl euler.pl
$ VAR1 = [ 5, 4, 3, 5, 2, 3, 1, 2, '4' ];