Php 树构建功能超出最大执行时间

Php 树构建功能超出最大执行时间,php,tree,hierarchy,Php,Tree,Hierarchy,我正在使用大约15000个节点,并试图从中构建层次结构。节点不能以任何方式进行排序,每个节点可以有无限数量的子节点,但父节点总是在其子节点之前被馈送到函数。我的代码适用于较小的N值,但最终超过了服务器上N>2000的最大执行时间。我不确定是否有更好的方法可以做到这一点,但我有以下几点: function insertNode(&$treeNode, $insertNode) { if($insertNode['DEPTH'] <= $treeNode['DEPTH']) r

我正在使用大约15000个节点,并试图从中构建层次结构。节点不能以任何方式进行排序,每个节点可以有无限数量的子节点,但父节点总是在其子节点之前被馈送到函数。我的代码适用于较小的N值,但最终超过了服务器上N>2000的最大执行时间。我不确定是否有更好的方法可以做到这一点,但我有以下几点:

function insertNode(&$treeNode, $insertNode) {
    if($insertNode['DEPTH'] <= $treeNode['DEPTH']) return false; 
    if($treeNode['ID'] == $insertNode['PARENT_ID']) {
        $treeNode['CHILDREN'][] = $insertNode;
        $treeNode['CHILD_COUNT']++;
        return true;
    }
    else {
        foreach($treeNode['CHILDREN'] as $key=>$value) {
            $found = insertNode($treeNode['CHILDREN'][$key], $insertNode);
            if($found) {
                $treeNode['CHILD_COUNT']++;
                return true;
            }
        }
    }
}
函数insertNode(&$treeNode,$insertNode){
if($insertNode['DEPTH']$value){
$found=insertNode($treeNode['CHILDREN'][$key],$insertNode);
如有($已找到){
$treeNode['CHILD_COUNT']++;
返回true;
}
}
}
}

我现在最好的解决方案是将递归限制为只构建数千个深度节点,然后在Javascript中调用每个底部节点的脚本,直到树真正完成。不过,我还是希望能一次完成所有的工作。

我自己想出来的。关键是:

家长们总是在孩子们面前被喂饱

我使用的SQL查询(Oracle
CONNECT BY
)直接在每个孩子(及其所有孩子)的直系祖先之后打印出来。例如,数据集:

|id|parent_id|
|A-|---------|
|C-|-----A---|
|Bb|-----B---|
|B-|-----A---|
将通过查询传递为:

|id|parent_id|
|A-|---------|
|B-|-----A---|
|Bb|-----B---|
|C-|-----A---|
我按顺序遍历查询的每一行,然后为每一行调用递归插入函数。在每个函数调用中,我使用
foreach
循环对树中当前节点的每个子节点进行递归调用,直到找到行的父节点,如下所示:

foreach($treeNode['CHILDREN'] as $key=>$value) {
    $found = insertNode($treeNode['CHILDREN'][$key], $insertNode);
    if($found) {
        $treeNode['CHILD_COUNT']++;
        return true;
    }
}
但是,由于每个子级的父级始终是其深度的最新插入项(因为它是我循环通过其深度的最后一行),因此父级保证是树最右边分支中最右边的子级。不仅循环是不必要的,实际上这是我能做的最糟糕的事情——从左到右循环子级,而且父级始终是最右边分支的最右边的子级,函数将循环并遍历的最后一项。(那是什么,
O(N^2)
?)难怪它超时了

我切断了foreach的
,取而代之的是一个调用

$lastChild = $treeNode['CHILDREN'];
end($lastChild);
$key = key($lastChild);
$found = insertNode($treeNode['CHILDREN'][$key], $insertNode);
if($found) {
    $treeNode['CHILD_COUNT']++;
    return true;
}

这大大缩短了执行时间,因为它以指数方式减少了每行函数递归调用自身的次数。它现在可以在6秒内为N=15000工作(在30秒的时候,它的上限低至N=2000)。不需要节点号上限或通过JS延迟加载。

…出现了野生递归!