如何在PHP中检测并避免无限循环

时间:2016-09-26 08:43:15

标签: php algorithm

这个问题不是关于我的PHP代码中的错误(目前我没有任何PHP脚本,我仍然在考虑算法)。这是问题所在:

我目前正在研究一个能够根据内部零件制造机械零件的机械零件管理器(例如,我有一件是自行车的一件,对于那件,我需要两个轮子,1车把,轮子我需要轮胎等。)

每个内部部件也是我数据库中的机械部件,并且与唯一ID链接(并且具有包含许多PDF,许多3D文件等的文件夹)。

我有一个代表我的数据库的GUI(用HTML),每个部分都有一个“Build”按钮来收集构建内部文件所需的所有文件。

例如:

我的自行车的ID为n°1,车轮的ID为n°2,车把的ID为n°3。

该算法非常简单,但容易受到无限循环的影响。

我怎么能避免这种情况:如果我的自行车(id 1)需要一个轮子(id 2),我的轮子需要一辆自行车......需要一个需要自行车的轮子.... ..?

非常感谢,

2 个答案:

答案 0 :(得分:4)

在执行构建函数期间,您只需跟踪已经生成结果的所有组件(在哈希中),如果再遇到其中一个,则忽略它。 / p>

以下是一些可用于启发的样板代码:

// Sample "database":
$components = array(
    1 => array (
        "id" => 1,
        "name" => "bike",
        "needs" => array (
            array ("id" => 2, "count" => 2), // 2 wheels
            array ("id" => 3, "count" => 1), // 1 handlebar
        ),
        "folder" => "/my/folders/bike"
    ),
    2 => array(
        "id" => 2,
        "name" => "weel",
        "needs" => array(
            array("id" => 4, "count" => 1), // 1 tire
            array("id" => 1, "count" => 1)  // 1 wheel?? - erroneous information!
        ),
        "folder" => "/my/folders/wheel"
    ),
    3 => array(
        "id" => 3,
        "name" => "handlebar",
        "needs" => array (),
        "folder" => "/my/folders/handlebar"
    ),
    4 => array(
        "id" => 4,
        "name" => "tire",
        "needs" => array(),
        "folder" => "/my/folders/tire"
    )
);  

// Build function: returns a list of folders related
// to all the parts of the given component.
function build($componentId, $components, $hash = array()) {
    // Protection against infinite recursion:
    if (isset($hash[$componentId])) return []; 
    $elem = $components[$componentId];
    // set hash, keyed by component ID.
    $hash[$componentId] = 1;
    // Add folder for this component
    $folders[] = $elem['folder'];
    // Collect folders of dependent components recursively
    foreach($elem['needs'] as $child ) {
        // ... pass the hash as third argument
        $folders = array_merge($folders, build($child["id"], $components, $hash));
    }
    return $folders;
}

// Example call: build component with ID 1, returning a list of folders:
print_r (build(1, $components));

上述代码的输出为:

Array
(
    [0] => /my/folders/bike
    [1] => /my/folders/wheel
    [2] => /my/folders/tire
    [3] => /my/folders/handlebar
)

因此,当第二次遇到自行车时,它被忽略了。

答案 1 :(得分:0)

你应该区分孩子与父母的关系。

自行车可以包含轮子作为子项目,轮子可以将自行车作为其父项目。另外一个螺钉和轮胎可以是轮子的儿童用品。

导航应该有一个方向,从父项到子项或相反。