使用perl进行递归查询

时间:2011-11-24 20:45:25

标签: algorithm perl dbi graph-algorithm

我在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中实现此类算法的最佳解决方案是什么?

2 个答案:

答案 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);