我在db上有以下表,它有2列:
from to
00001 00002
00001 00003
00002 00003
00002 00004
00003 00001
00003 00004
00002 00004
00004 00002
00005 00003
00005 00001
00006 00007
00009 00006
我需要使用perl和dbi连接特定的数字,例如00001的输出将是以下连接:
00001 00002 0003 00004 00005
因为00001连接到00002和00003以及00002和00003连接到那些新号码00004和00005。
是否有算法实现这一点以及perl中实现此类算法的最佳解决方案是什么?
答案 0 :(得分:1)
似乎你想要找到一个连接的子树(它是一个有向图,例如一棵树,所以你想要树算法)。
这是使用树搜索算法完成的 - DFS(深度优先搜索)或BFS(呼吸优先搜索)。您可以在SQL或Perl中实现一个(或者在DBI混合中实现,但它比纯SQL或纯Perl解决方案更烦人)。
一般的BFS将是:
创建一个队列(提示:在Perl中,队列和堆栈自然由数组表示)
将原始节点存储在队列中。
队列不为空时,请重复:
从队列中弹出第一个节点N
。
将该节点标记为“已遍历”。最简单的方法是将%seen
哈希中的哈希元素设置为N
,其值为{。
将N
打印到路径
从 N中连接的数据库中查找所有节点。
将最后一步中尚未看到的节点添加到队列末尾。
结束循环。
答案 1 :(得分:-2)
一种可能的方法:
sub AllReachable {
my ( $dbi, $sql, @todo ) = @_;
my %done;
while (@todo) {
my $res = $dbi->selectcol_arrayref( sprintf $sql, join( ",", @todo ) );
@done{@todo} = ();
@todo = grep {!exists $done{$_}} @$res;
}
return keys %done;
}
my @result = AllReachable($dbi, 'SELECT DISTINCT to FROM table WHERE from IN (%s)', 1);