修改的预订树遍历中的路径

时间:2011-09-01 21:45:00

标签: php mysql algorithm

我已经实现了修改后的预订树遍历as explained here。我的树是这样的:

+-------+-----------+-----+-----+
| ref   | name      | lft | rgt |
+-------+-----------+-----+-----+
|  NULL | base      |   1 |   8 | 
|     2 | basic     |   2 |   3 | 
|  NULL | listener  |   4 |   7 | 
|     1 | test      |   5 |   6 | 
+-------+-----------+-----+-----+

一切都很好,但现在我尝试基于路径实现PHP搜索功能,它是这样的:

$result = searchTree('base.listener.test');
// Now $result is an array with node {1, test}

这意味着searchTree根据给定的路径返回子树。如果路径不存在,它将返回一个空数组。

我当前的实现是一个循环函数,它将树加载到PHP数组中,然后分割路径并遍历数组。它似乎是一个不可扩展的实现......任何更好的实现(可能使用mySQL查询?)。

我目前的实施是这样的。首先,我得到整个树(SELECT * FROM树),然后我执行此函数从这个数据创建一个多维数组:

function create_tree($results) {
    $return = $results[0];
    array_shift($results);

    if ($return['lft'] + 1 == $return['rgt'])
        $return['leaf'] = true;
    else {
        foreach ($results as $key => $result) {
            if ($result['lft'] > $return['rgt'])
                break;
            if ($rgt > $result['lft'])
                continue;
            $return['children'][] = create_tree(array_values($results));
            foreach ($results as $child_key => $child) {
                if ($child['rgt'] < $result['rgt'])
                    unset($results[$child_key]);
            }
            $rgt = $result['rgt'];
            unset($results[$key]);
        }
    }

    unset($return['lft'],$return['rgt']);
    return $return;
}

然后我在 $ tree 变量中有一个数组并执行这段代码:

$t3 = $tree;
$parts = explode('.', $path);
while (isset($parts[0]) && count($parts) > 1 && isset($t3['children']) && $parts[0] == $t3['name']) {
    array_shift($parts);
    for ($i = 0;  $i < count($tree['children']) && $tree['children'][$i]['name'] != $parts[0];  $i++);
    $t3 = $tree['children'][$i];
}

return isset($t3) && count($parts) == 1 && $parts[0] == $t3['name']? $t3['children'] : array();

最后一行返回$ path指向的节点(即'base.listener.test'),如果此路径不存在则返回一个空数组。

1 个答案:

答案 0 :(得分:0)

如果我理解你在寻找什么,你想打电话:

$result = searchTree('test');

并在数据库中搜索父母?

SELECT p.name
    FROM tree c
    INNER JOIN tree p ON p.lft < c.lft AND p.rgt > c.rgt
    WHERE c.name = 'test'
    ORDER BY p.lft;