使用PHP检测MySQL数据库中的周期
我在MySQL中有一个表,有两个(重要)列,a和B,其值引用一个包。当且仅当包A对包B有要求时,表中有一行 我希望(1)用php生成一个图,然后(2)确定该图是否是非循环的(DAG),如果不是,则打印(3)图中的所有循环 所以3在理论上是很容易的,(约翰逊的算法:) (2) 可以通过(3)列出没有循环来完成,但我想知道是否有更快的算法 我不确定(1)-高效地从表中提取数据,并用php生成一个适合于实现(2)和(3)的图形。我应该怎样做使用PHP检测MySQL数据库中的周期,php,mysql,graph,cycle,Php,Mysql,Graph,Cycle,我在MySQL中有一个表,有两个(重要)列,a和B,其值引用一个包。当且仅当包A对包B有要求时,表中有一行 我希望(1)用php生成一个图,然后(2)确定该图是否是非循环的(DAG),如果不是,则打印(3)图中的所有循环 所以3在理论上是很容易的,(约翰逊的算法:) (2) 可以通过(3)列出没有循环来完成,但我想知道是否有更快的算法 我不确定(1)-高效地从表中提取数据,并用php生成一个适合于实现(2)和(3)的图形。我应该怎样做 另外,我还有第二个表,也有两列,当且仅当a与B冲突时才有一
另外,我还有第二个表,也有两列,当且仅当a与B冲突时才有一行。我还想(4)查找案例(或验证没有案例),其中:
A需要B,B需要C,但A与C的冲突听起来像是“请帮我做作业” 在渲染图形方面——看看graphviz——这将生成各种图形。它解析PHP源代码以获取调用图 对不起,我已经够忙了,没有阅读你提供的参考资料(但在提供到你的源材料的链接方面做得很好),也没有研究出他们使用的算法,然后思考它是否是最优的
您可能想看看新的PHP垃圾收集器的源代码,它也做同样的事情。(实际上,你只需要在树上走一走——如果你来到一个你已经访问过的节点,那么你就有了一个循环)。为了在搜索中找到这个主题的任何人的利益 (1) (2)和(3) 我最终使用了这个算法。基本上,通过删除叶节点,您要么留下一个(一组)循环,要么留下一个空图
$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";
}
}
}
$allReqs=$reqEdgeList;
$noDependanciesCycle=true;
$search=true;
同时($搜索){
if(空($pkgList)){
$search=false;
echo“Req是一个DAG\n
”;
}否则{
$foundleaf=false;
$leaf=null;
foreach($pkgList作为$key=>l){
$isLeaf=true;
foreach($reqEdgeList为$k=>$edge){
如果($edge[0]==$l){
$isLeaf=false;
}
}
如果($isLeaf){
$foundleaf=true;
$leaf=$l;
}
}
如果($foundleaf){
$pkgList=array_diff($pkgList,array($leaf));
foreach($requedgelistas$key=>$value){
如果($value[1]=$leaf){
未设置($REQUEDGELIST[$key]);
}
}
$reqEdgeList=数组值($reqEdgeList);
}否则{
$search=false;
echo“检测到请求周期\n
”;
$noDependanciesCycle=false;
打印(需求列表);
回显“
\n”;
}
}
}
(4)
为了找到A需要B需要C,但A与C冲突,我对每个冲突使用深度优先搜索,从A开始,寻找C(冲突)
$reqEdgeList=$allReqs;
回显“
\n”;
$anyReqConfError=假;
foreach($conedgelistas$endpoints){
对于($i=0;$i<2;$i++){
如果($i==0){
$startPkg=$endpoints[0];
$endPkg=$endpoints[1];
}否则{
$startPkg=$endpoints[1];
$endPkg=$endpoints[0];
}
$marked=array();
foreach($allPkgs作为$pkg){
$marked[$pkg]=false;
}
$queue=array();
$queue[]=$startPkg;//enque
$marked[$startPkg]=真;
$search=true;
$found=false;
同时($搜索){
$v=array\u shift($queue);//deque(对堆栈(dfs)使用array\u pop)
如果($v==$endPkg){
$search=false;
$found=true;
}否则{
foreach($REQUEDGELIST as$edge){
如果($edge[0]==$v){
$w=$edge[1];
如果(!$标记为[$w]){
$marked[$w]=真;
$queue[]=$w;
}
}
}
}
如果($搜索){
$search=!empty($queue);
}
}
如有($已找到){
echo“$startPkg需要$endPkg,但存在冲突[$endpoints[0]$endpoints[1]]]\n
”;
$anyReqConfError=真;
$noDependanciesCycle=false;
}
}
}
如果我误导了你,我将不胜感激,但我不是在问如何实现我找到的算法,我是在问(1)在PHP中从MySQL数据生成图形(如组合/数据结构类型)和(2)在PHP中进行图形遍历的最佳实践是什么。我对图形绘制不感兴趣,但谢谢你的链接。我不是要你告诉我一些模糊的算法是否适合我的任务(当然,这是我的工作)或者如何实现它,而是建议另一个(如果你知道的话),更重要的是建议(链接到)与(1)和(2)相关的示例代码。我还应该提到,这不是家庭作业,而是实际工作——我已经在其他语言中实现了图形遍历,我只是想了解其他人是如何在PHP中实现的,特别是在MySQL data.Finite中,但除此之外,不。我可能有一个很长的链,比如a=>B=>C=>…=>Z=>a。我还应该澄清,它可能是一个定向林,而不仅仅是一棵树(即未连接)。
$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";
}
}
}
$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;
}
}
}