使用PHP检测MySQL数据库中的循环

时间:2011-02-08 10:02:09

标签: php mysql graph cycle

我在MySQL中有一个包含两个(重要)列A和B的表,其值指的是一个包。当且仅当包A在包B上需要时,表中才有一行。

我希望(1)在php中生成图表,然后(2)确定图表是非循环的(DAG),如果不是,则打印(3)图表中的所有周期。

理论上,3很容易(Johnson的算法:http://dutta.csc.ncsu.edu/csc791_spring07/wrap/circuits_johnson.pdf)。

(2)可以通过(3)列出没有循环来完成,但我想知道是否有更快的算法。

我不确定(1) - 有效地从表中提取数据并在php中制作图表,这有助于实现(2)和(3)。我该怎么办?


顺便说一下,我还有第二个表,也有两列,当且仅当A与B冲突时才有一行。我还想(4)查找案例(或验证那里没有)其中: A要求B,B要求C,但A与C

冲突

2 个答案:

答案 0 :(得分:2)

为了在搜索中找到此主题的任何人的利益

<强>(1)

$pkgList = array();
$result = mysqli_query($conn, 'SELECT * FROM `Packages`');
while (($row = mysqli_fetch_array($result, MYSQLI_ASSOC)) != NULL) {
    $pkgList[] = $row['idPackages'];
}

$reqEdgeList = array();
$conEdgeList = array();

$result = mysqli_query($conn, "SELECT * FROM `Dependancies` WHERE `Relationship` = 'Requires'");
while (($row = mysqli_fetch_array($result, MYSQLI_ASSOC)) != NULL) {
    switch ($row['Relationship']) {
        case 'Requires':
            $reqEdgeList[] = array($row["DependerPackage"], $row["DependeePackage"]);
            break;
        case 'Conflicts':
            $conEdgeList[] = array($row["DependerPackage"], $row["DependeePackage"]);
            break;
    }
}

(2)(3)

我最终使用了算法here。基本上通过删除叶节点,您可以留下一组(一组)循环或一个空图。

$allReqs = $reqEdgeList;

$noDependanciesCycle = true;

$searching = true;
while ($searching) {
    if (empty($pkgList)) {
        $searching = false;
        echo "Req is a DAG\n<br />";
    } else {
        $foundleaf = false;
        $leaf = null;
        foreach ($pkgList as $key => $l) {
            $isLeaf = true;
            foreach ($reqEdgeList as $k => $edge) {
                if ($edge[0] == $l) {
                    $isLeaf = false;
                }
            }

            if ($isLeaf) {
                $foundleaf = true;
                $leaf = $l;
            }
        }
        if ($foundleaf) {
            $pkgList = array_diff($pkgList, array($leaf));
            foreach ($reqEdgeList as $key => $value) {
                if ($value[1] == $leaf) {
                    unset($reqEdgeList[$key]);
                }
            }
            $reqEdgeList = array_values($reqEdgeList);
        } else {
            $searching = false;
            echo "Req cycle detected\n<br />";
            $noDependanciesCycle = false;
            print_r($reqEdgeList);
            echo "<br />\n";
        }
    }
}

<强>(4)

为了找到A要求B需要C,但A与C冲突,我使用深度优先搜索每个冲突,从A开始,寻找C(冲突)。

$reqEdgeList = $allReqs;
echo "<br />\n";

$anyReqConfError = false;
foreach ($conEdgeList as $endpoints) {
    for ($i = 0; $i < 2; $i++) {
        if ($i == 0) {
            $startPkg = $endpoints[0];
            $endPkg = $endpoints[1];
        } else {
            $startPkg = $endpoints[1];
            $endPkg = $endpoints[0];
        }

        $marked = array();
        foreach ($allPkgs as $pkg) {
            $marked[$pkg] = false;
        }

        $queue = array();
        $queue[] = $startPkg; // enque
        $marked[$startPkg] = true;

        $searching = true;
        $found = false;
        while ($searching) {
            $v = array_shift($queue); // deque (use array_pop for stack (dfs))
            if ($v == $endPkg) {
                $searching = false;
                $found = true;
            } else {
                foreach ($reqEdgeList as $edge) {
                    if ($edge[0] == $v) {
                        $w = $edge[1];
                        if (!$marked[$w]) {
                            $marked[$w] = true;
                            $queue[] = $w;
                        }
                    }
                }
            }

            if($searching) {
                $searching = !empty($queue);
            }
        }

        if($found) {
            echo "$startPkg requires $endPkg, but are conflicting [$endpoints[0] $endpoints[1]]\n<br />";
            $anyReqConfError = true;
            $noDependanciesCycle = false;
        }
    }
}

我很感激您对此答案的评论中的任何代码审核

答案 1 :(得分:-1)

听起来很奇怪'请帮我做作业'。

在渲染图形方面 - 看看graphviz - 这将生成各种图形。 Here's an example解析PHP源代码以获取调用图。

很抱歉,但是我很忙,没有阅读您提供的参考资料(但是提供了源材料的链接做得很好)并计算出他们使用的算法,然后考虑它是否是最佳的。

您可能希望查看新的PHP垃圾收集器的源代码 - 它执行相同的操作。 (实际上你只需要走树 - 如果你来到一个已经访问过的节点,那么你就有了一个循环)。