PHP中的拓扑排序

PHP中的拓扑排序,php,algorithm,Php,Algorithm,我找到了PHP的拓扑排序函数: 资料来源: 我看起来又漂亮又矮。无论如何,对于一些输入-我在输出中得到重复的行-请参阅 通常,如果使用array\u unique() 我用两个例子检查了这个函数,排序本身看起来是正确的 我是否应该对结果调用array\u unique()?因为存在重复的边,所以会得到重复的行。我不是图论暴徒,但我很确定这是不合法的: 0 => array ( 0 => 'nominal', 1 => 'subtotal', ), 2 => a

我找到了PHP的拓扑排序函数:

资料来源:

我看起来又漂亮又矮。无论如何,对于一些输入-我在输出中得到重复的行-请参阅

通常,如果使用
array\u unique()

我用两个例子检查了这个函数,排序本身看起来是正确的


我是否应该对结果调用
array\u unique()

因为存在重复的边,所以会得到重复的行。我不是图论暴徒,但我很确定这是不合法的:

0 => 
array (
  0 => 'nominal',
  1 => 'subtotal',
),
2 => 
array (
  0 => 'nominal',
  1 => 'subtotal',
),
...
您可以在构造节点的零件中添加测试,如下所示:

if ($id==$e[0] && !in_array($e[1], $nodes[$id]['out']))
{
  $nodes[$id]['out'][]=$e[1];
}
if ($id==$e[1] && !in_array($e[0], $nodes[$id]['in'])) // Not needed but cleaner
{
  $nodes[$id]['in'][]=$e[0];
}

。。。或者确保不将重复的边传递给函数:P

我是原始拓扑排序函数的作者。感谢Alex提醒我注意重复边缘问题。我已更新该函数以正确删除重复的边和节点。更新版本如下:

(与原链接相同)

我添加了以下内容以实现重复数据消除:

// remove duplicate nodes
$nodeids = array_unique($nodeids);  

// remove duplicate edges
$hashes = array();
foreach($edges as $k=>$e) {
    $hash = md5(serialize($e));
    if (in_array($hash, $hashes)) { unset($edges[$k]); }
    else { $hashes[] = $hash; }; 
}

我必须序列化边缘,以确保正确删除重复的边缘。我还整理了函数的其余部分,并添加了一些注释。

根据您想要的输出,这是一个修复。我没有正确地检查代码以确定它是否正确,但它确实解决了您报告的问题。从EE 1.12升级到1.13时,我体验到为订单发票创建了循环图。您可能希望抛出带有明确错误消息的异常,而不是返回null,因为将生成错误/无总计。返回null只会导致一个PHP警告,因为PHP以后需要一个数组。一个异常将更容易调试,而且您必须采取行动也会更清楚。嗨,丹,谢谢您分享您的算法。您是否知道,如果可能的话,可以通过另一种方式使函数支持树内的循环链接—比如,如果有一些循环链接,只使用第一个循环链接而忽略所有下一个循环链接(不返回null)。我有一个节点树,它们已经从数据库中获得了一些顺序,比如1,2,3,4。如果有像[1,2],[2,3],[3,1]这样的边,我想忽略[3,1],因为它是一个循环。
// remove duplicate nodes
$nodeids = array_unique($nodeids);  

// remove duplicate edges
$hashes = array();
foreach($edges as $k=>$e) {
    $hash = md5(serialize($e));
    if (in_array($hash, $hashes)) { unset($edges[$k]); }
    else { $hashes[] = $hash; }; 
}