【发布时间】:2020-01-23 17:06:56
【问题描述】:
我有一个格式如下的文件:
Y1DP480P T FDVII005 ID=000
Y1DPMS7M T Y1DP480P ID=000
Y1DPMS7M T Y1DP4860 ID=000
Y1DPMS7M T Y1ENDCYP ID=000
Y1DPMS6M T Y1DPMS7M ID=000
Y1DPMS5M T VPY1CM28 ID=000
Y1DPMS5M T Y1DPMS6M ID=000
Y1DPAS21 T Y1DPMS5M ID=000
Y1DPMS4M T FDRBC004 ID=000
Y1DPMS4M T FDYBL004 ID=000
等等。等等
仅使用1-8列和12-19列的数据,可以认为是:
node1 -> node2
node1 -> node3
node3 -> node5
node2 -> node4
node4 -> node5
node5 -> node7
我需要一种有效的方法来映射从给定起始节点到给定结束节点的路径。
例如,如果我想要从 node1 到 node7 的路径,该函数将返回 node1->node3, node3->node5, node5->node7。
目前的做法:
我将文件读入一个数组,将前 19 个字符作为键和值,例如
$data[Y1DP480P T FDVII005] = 'Y1DP480P T FDVII005'
(我使用值作为键,因为输入文件可能包含重复项,因为这会将它们过滤掉 - 我不认为 PHP 具有“设置”数据结构)。
我有一个递归子例程,可以从给定节点中找到下一个“n”个依赖项,如下所示:
(入口时,$path[]是一个空数组,节点数据在$data中,开始搜索的节点是$job,依赖的深度是$depth)
function createPathFrom($data, $job, $depth) {
global $path, $maxDepth, $timeStart;
$job = trim($job);
// echo "Looking for $job\n";
if ( $depth > $maxDepth ) {return;} // Search depth exceeded
// if ( (microtime(true) - $timeStart) > 70 ) {return;} //Might not be needed as we have the same further down
// $depth += 1;
// Get the initial list of predecessors for this job.
// echo __FUNCTION__."New iteration at depth $depth for $job\n";
$dependents = array_filter($data, function($dataLine) use($job){
// preg_match('/'.JOB_SPLIT_MASK.'/', $dataLine, $result);
// $dependent = trim($result[1]);
$dependent = explode(" ", $dataLine)[0];
return ( $dependent == $job );
// return ( preg_match('/'.$job.'/', $dependent) );
});
if (count($dependents) == 0) {
return;
} else {
// print_r($predecessors);
$elapsedTime = microtime(true) - $timeStart;
// print $elapsedTime." : Searching ".count($dependents)." at depth ".$depth.NL;
$path = array_merge($path, $dependents);
foreach($dependents as $dependency) {
// preg_match('/'.JOB_SPLIT_MASK.'/', $dependency, $result);
// $dependent = trim($result[3]);
$dependent = explode(" ", $dependency)[2];
if ( (microtime(true) - $timeStart) > 85 ) {return;} // Let's get out if running out of time... (90s in HTTPD/conf)
createPathFrom($data, $dependent, $depth+1);
}
}
}
我有一个几乎相同的函数,它为我的终端节点建立了前辈,称为createPathTo
时间限制(70 秒和 85 秒,是的 - 绝对是多余的)和深度限制是为了避免我的 cgi 脚本超时。
如果我以足够的“深度”调用这两个例程,我可以查看它们是否连接,但有很多死胡同。
我认为我正在进行广度优先搜索,而我认为我应该进行深度优先搜索并丢弃未到达目标节点的搜索。
问题:
给定一个开始节点和一个结束节点,是否有高效的搜索算法将返回最少的节点以建立连接或指示未找到路径的某个值?
这个问题来自Recursive function in PHP to find path between arbitrary nodes。我有通往(现在从)我的目标节点的节点,但现在我想将它修剪为仅 2 个节点之间的路径。
编辑:我确定答案已经在 SO 上,但我对 PHP 和这类算法还很陌生,所以一直找不到。
【问题讨论】:
标签: php algorithm depth-first-search breadth-first-search