我有以下图表
my %connections=(36=>[31,22],31=>[30],30=>[20],22=>[20,8],20=>[1],8=>[5],5=>[2],2=>[1,20]);
是否有任何现有的算法可以让我们找到只有传出边和只有传入边的节点。 因此,鉴于上图,它将产生:
$node_only_incoming_edge = [36];
$node_only_outgoing_edge = [1];
创建的图表
更新:根据RF建议修正了%connection
条目错误。
答案 0 :(得分:4)
Richard Fearn的回答描述了自己计算结果的算法。另一种方法是使用Graph模块。例如:
use strict;
use warnings;
use Graph;
my $g = Graph->new;
my %connections = (
36 => [31,22],
31 => [22,30], # Your data omitted 22.
30 => [20],
22 => [20,8],
20 => [1,99], # Added 99 for testing.
8 => [5],
5 => [2],
2 => [1,20],
88 => [31], # Added 88 for testing.
);
for my $n (keys %connections){
$g->add_edge($n, $_) for @{$connections{$n}};
}
my @outgoing_only = $g->source_vertices; # 36 and 88
my @incoming_only = $g->successorless_vertices; # 1 and 99
答案 1 :(得分:2)
只有传出边的节点将在connections
字典中有一个条目(表示该节点到一个或多个其他节点有一条边),但该节点不会显示在任何一个节点的值中字典的条目(表示该节点与其他节点之间存在边缘)。
只有传入边缘的节点不在connections
字典中有一个条目(意味着从那个节点到任何其他节点没有边缘) 。但是会出现在一个或多个字典条目的值中(意味着该节点有一个边缘到)。
答案 2 :(得分:1)
虽然我觉得我更喜欢FM更好,但为了我自己的乐趣,我实施了Richard的:
#!/usr/bin/perl
use strict;
use warnings;
my %connections=(36=>[31,22],31=>[30],30=>[20],22=>[20,8],20=>[1],8=>[5],5=>[2],2=>[1,20]);
my @left = keys %connections;
my @only_incoming;
my @arrives;
my @only_outgoing;
my @all_nodes = @left;
foreach my $left (@left) {
foreach my $arrives (@{ $connections{$left} }) {
unless ($arrives ~~ @arrives) {
push(@arrives, $arrives);
push(@all_nodes, $arrives) unless $arrives ~~ @all_nodes;
}
}
}
foreach my $node (@all_nodes) {
if ($node ~~ @left and !($node ~~ @arrives)) {
push(@only_incoming, $node);
} elsif (!($node ~~ @left) and $node ~~ @arrives) {
push(@only_outgoing, $node);
}
}
print "Only incoming: " . join(" ", @only_incoming) . "\n";
print "Only outgoing: " . join(" ", @only_outgoing) . "\n";