如何使用dijkstram打印具有如此多链接的图形路径?

时间:2012-01-01 09:00:27

标签: perl graph

我有57个节点和204个链接的无向图。我使用Dijkstram算法计算所有节点及其子节点的最短路径,但我无法从给定的根打印节点的路径。这是我尝试的方式。

########## the dijkstram algorithm#################
sub dijkstra {
    my ($graph, $root) = @_;
    my (%dist, %prev);

    foreach $n (keys %{$graph}) { $dist{$n} = inf; $prev{$n}=$n; }
    # .. except the source
    $dist{$root} = 0;

    # loop while we have unsolved nodes
    # sort unsolved by distance from root
    foreach my $n1 (sort keys %{$graph}) {
        foreach my $n2 (keys %{$graph->{$n1}}) {
            if (($dist{$n2} eq inf)) {
                $dist{$n2} = $dist{$n1} + $graph->{$n1}{$n2};
                $prev{$n2} = $n1;
            }
        }
    }
    return (\%prev, \%dist);
}
######## print the path and the distance for a given node#############
sub printPaths {
    my ($graph, $prev, $dist) = @_;
    my $path;

    foreach $n (keys %{$graph}) {
        my $t = $n;
        $path = $t;
        while ($t ne $root) {
            $t = $prev->{$t}; $path = "$t -> " . $path;
        }
        print "$n\t$dist->{$n}\t$path\n";
    }
}

问题发生在while循环上。当它获得一个没有相同根的节点,并且当前一个节点总是返回同一个节点时。请帮帮我或给我任何建议。感谢

1 个答案:

答案 0 :(得分:0)

警告:我没有您的问题域的经验,所以这可能不是答案本身。然而,我提供了一些关于问题可能存在的指示(希望如此)。

我使用prot.ini中的以下数据集运行您的代码:

ARR1 MafB
MafB JunD
ARR1 MET4
ARR1 ATF1
ARR1 BACH1
ARR1 CHOP 
ATF1 BACH1
ATF1 MET4
ATF1 NFE2L1
ATF2 ATF7
ATF2 BATF

(为了便于阅读,删除了大肆宣传!)

在dijkstra函数%prev看起来像这样:

$prev = {
          'ATF1' => 'ARR1',
          'MafB' => 'ARR1',
          'BACH1' => 'ARR1',
          'BATF' => 'ATF2',     # problem here
          'ATF2' => 'BATF',     # values are cyclic
          'CHOP' => 'ARR1',
          'ARR1' => 'ARR1',
          'JunD' => 'MafB',
          'NFE2L1' => 'ATF1',
          'ATF7' => 'ATF2',      
          'MET4' => 'ARR1'
        };

在你的print_path中,while循环$ t在'BATF'和'ATF2'之间无休止地交替。

您可以在print_path函数中检测到这一点 - 但我最终在dijkstra函数中添加以下行以防止出现循环问题:

if (($dist{$node2} eq inf)) {
  $dist{$node2} = $dist{$node1} + $graph->{$node1}{$node2};
  if ($prev{$node1} ne $node2) {
    $prev{$node2} = $node1;
  }
}

然后我修改了print_path函数中的while循环:

while ($tmp ne $root) {
    $tmp = $prev->{$tmp};
    last unless $tmp;
    $path = "$tmp -> $path";
}

另外我注意到这一行:

$dist{$node2} = $dist{$node1} + $graph->{$node1}{$node2};

$ dist {$ node1}可能是无穷大:所以结果仍然是无穷大。不确定这是否是故意的。

希望这有帮助。