用于查找不能处理大文件的最短路径的Perl代码

时间:2014-07-25 06:43:24

标签: perl graph shortest-path

我有这个代码,它接收一个输入文件并打印出从每个孩子到父母的最短路径" Q"。每个孩子都必须找到最短的路径来解决问题。只有,如果该路径存在,则打印else打印空白。

perl short_path.pl input_fie output_file

#! /usr/bin/perl



#=======================Processing the input file========================#
print "Enter file name:\n";
chomp(my $file = <STDIN>);
open(DATA,$file) or die "failed opening file!!";
my %DEF = (
  I   => [qw( P Pl P.P P.Pl Pl.P Pl.Pl P.P.P P.P.Pl P.Pl.P P.Pl.Pl Pl.P.P Pl.P.Pl Pl.Pl.P Pl.Pl.Pl )],
  II  => [qw( E P.E Pl.E P.P.E P.Pl.E Pl.P.E Pl.Pl.E )],
  III => [qw( E.P E.Pl P.E.P P.E.Pl Pl.E.P Pl.E.Pl E.P.P E.P.Pl E.Pl.P E.Pl.Pl )],
  IV  => [qw( E.E P.E.E Pl.E.E E.P.E E.Pl.E E.E.P E.E.Pl E.E.E )]
); # Hash table/dictionary for all the  groups
my @rank = map @$_, @DEF{qw(I II III IV)};
my %rank = map {$rank[$_-1] => $_} 1..@rank;
my @group = map {($_) x @{$DEF{$_}}} qw(I II III IV);
my %group = map {$rank[$_-1] => $group[$_-1]."_".$_} 1..@group;
sub rank { $rank{$a->[2]} <=> $rank{$b->[2]} }

my %T;

sub oh { map values %$_, @_ }
sub ab {
  my ($b, $a) = @_;
  [$b->[0], $a->[1], qq($a->[2].$b->[2]), qq($b->[3]<-$a->[3])]
}
sub xtend {
  my $a = shift;
  map {ab $_, $a} oh @{$T{$a->[0]}}{@_}
}
sub ins { $T{$_[3] //= $_[1]}{$_[2]}{$_[0]} = \@_ }

ins split /,\s*/ for <DATA>;
#ins split /,\s*/ for $filename;
ins @$_ for map {xtend $_, qw(P E Pl)} (oh oh oh \%T);
ins @$_ for map {xtend $_, qw(P E Pl)} (oh oh oh \%T);

for (sort {rank} grep {$_->[1] eq 'Q'} (oh oh oh \%T)) {
  printf "%-4s: %20s,  %-8s %6s\n",
      $_->[0], qq($_->[0]<-$_->[3]), $_->[2], $group{$_->[2]};
}

该程序在下面提到的小样本文件中正常工作。

SAMPLE_INPUT

(第1列是子,第2列是其父,第3列是关系)。因此例如第一行表示,M19是Q的子,关系是P。

M19,Q,P,
M31,M19,Pl,
M420,M31,E,
M421,M31,E,
M33,M31,E,
M438,M33,Pl,
M445,M33,E,
M437,M33,E,
M444,M33,E,
M73,M33,E,
M552,M73,Pl,
M553,M73,Pl,
M569,M73,E,
M549,M73,E,
M550,M73,E,
M73,Q,P,

输出

(第1列表示子级,第2列是从该子级到父级的最短路径&#34; Q&#34;如果存在,第3列是每个单独路径的级联关系,第4列是来自DEF的group_id。 )

M19 :               M19<-Q,  P           I_1
M73 :               M73<-Q,  P           I_1
M31 :          M31<-M19<-Q,  P.Pl        I_4
M552:         M552<-M73<-Q,  P.Pl        I_4
M553:         M553<-M73<-Q,  P.Pl        I_4
M549:         M549<-M73<-Q,  P.E       II_16
M569:         M569<-M73<-Q,  P.E       II_16
M550:         M550<-M73<-Q,  P.E       II_16
M33 :     M33<-M31<-M19<-Q,  P.Pl.E    II_19
M420:    M420<-M31<-M19<-Q,  P.Pl.E    II_19
M421:    M421<-M31<-M19<-Q,  P.Pl.E    II_19

但是对于这个文件http://qfs.mobi/f1508588

的下载链接而言输入文件为2000行失败了

请帮我解决这个问题。

======代码急需解释====

对不起,我很抱歉,但是希望我足够清楚。

考虑输入文件: Eve,BigDaddy,Father John,Eve,Son John,Chang,Son Chang,Eve,Mother 现在我们必须找到每个孩子到BigDaddy的最短路径。 所以在这种情况下考虑第一列,我们有3个孩子:Eve,John,Chang。

第三列是第二列与第一列的关系。

对于他们每个人,我们需要找到他们与BigDaddy的最短链接(或者#34; Q&#34;正如我在示例输入文件中所示。&#34; Q&#34;是BigDaddyin的样本输入案例。 所以对于Eve来说,我们已经有了通往BigDaddy的最短途径

Eve : Eve<-BigDaddy, Father , Male_relations_1

对于约翰而言,约翰与前夕有关(儿子),夏娃是BigDaddy(父亲)。因此,第三列将连接它们的关系:

John: John<-Eve<-BigDaddy, Son.Father , Male_relations_5

第四列是这些连接关系的Relation id。这些关系id的集合已经给出(正如你在代码中看到的那样,它在hash%DEF中)。例如

DEF = ( Male_relations => [qw(Father Father.Son Son Brother Son.Father.....)], Female_relations => [qw(Mother Mother.Son Aunt Aunt.Father ....)])

John和BigDaddy之间的连接关系是Son.Father,它是Male_relations中的第5个,因此我们表示Male_relations_5

0 个答案:

没有答案