【问题标题】:Can't get to show all of a tree in a traversal preorder in php无法在php中以遍历预顺序显示所有树
【发布时间】:2018-08-20 20:26:03
【问题描述】:

我的数据库中有一个表,其中包含许多家谱树。

-----------------------------
- id  name              parent_id
-----------------------------
- 1   grandfather       NULL
- 2   father            1
- 3   uncle             1
- 4   son               2
- 5   brother           2
- 6   cousin's dauther  7
- 7   cousin            8
- 8   auntie            1

问题是由于边缘情况,我无法显示所有名称:

-当我有一个人的 parent_id 大于它的 parent_id 时 (见表弟的女儿)

我使用这个查询来获取表格:

    $sql = "SELECT p1.id, p1.name, p1.parent_id FROM pariente p1 
    ORDER BY p1.parent_id";
    $result = $conn->query($sql);

问题是,如果我使用“ORDER BY parent_id”,“cousin's dauther”将不会显示,如果我使用“ORDER BY id”,“cousin”将不会显示。

我使用这个函数将树变成一个数组并绘制它:

        function make_tree($data, $root) {
            $tree = [];
            foreach ($data as $node) {
                insert($tree, $node);
            }

            return $tree;
        }

        function insert(&$root, &$node) {
            if (!$root) {
                $root = $node;
            }
            else if ($root["id"] === $node["parent_id"]) {
                $root["children"][] = $node;
            }
            else if (array_key_exists("children", $root)) {
                foreach ($root["children"] as &$c) {
                    if (insert($c, $node)) {
                        break;
                    }
                }
            }
        }

        function preorder2(&$root) {
            if ($root) {
                echo "<li>";
                echo $root["name"];

                if (array_key_exists("children", $root)) {
                    echo "<ul>";
                    foreach ($root["children"] as $c) {
                        preorder2($c);
                    }
                    echo "</ul>";
                }
                echo "</li>";
            }
        }
    ?>

在我使用它调用函数之后:

<div>

<?php
while( $row = mysqli_fetch_assoc( $result)){
    $resguard[] = $row;
}
    $tree = make_tree($resguard);
    preorder2($tree);
?>
</div>

【问题讨论】:

    标签: php database tree genealogy


    【解决方案1】:

    我曾经遇到过类似的问题,下面是我的解决方法。

    1. 遍历数据集,将每个节点放入数组中,并跟踪您希望成为根节点的节点。

    2. 遍历数组。对于每个 parent_id 不为 null 的节点,通过 id 查找父节点,并将当前节点添加为子节点。构建树时无需使用递归。

    【讨论】:

    • 在实际版本中,我的桌子上有 1400 多人。如果我了解您的解决方案,我必须首先使用所有根(parent_id=null)填充数组,然后在遍历表后将子项添加到表中已有的每个节点。这是一个不错的方法,但我无法想象如何添加所有节点,我应该通过表格检查孩子多少次,表格中的每个人一次?或者我应该使用什么条件?在第一次迭代中,它已经添加了大多数人。
    • 您浏览列表两次。第一个将节点放入以 ID 为键的数组中,因此您可以立即查找它。第二次将每个孩子与父母联系起来。在每个节点都可以通过 id 查找之前,不要添加子节点。这样你就可以全部搞定。作为一项优势,您现在还可以通过 id 访问每个节点,而无需搜索结果或树。
    • 这听起来很不错,但是这种结构可以进行前序遍历吗?
    • @ggorlen 当然可以!只需保留一个指向根节点的引用/指针,然后依次访问当前节点和子节点。
    【解决方案2】:

    最后我相信我没有得到烤面包机的答案,但它让我思考并最终解决了问题(仍然使用 ggorlen 显示树的方式)。

    首先这是查询:

    $sql = "SELECT p1.id, p2.name, p2.id as minor, p2.name FROM pariente p1 INNER JOIN pariente p2 ON p1.id = p2.parent_id ORDER BY p1.id";
    $result = $conn->query($sql);
    
    $sql2 = "SELECT p1.id, p1.nombre, p1.padre_id FROM pariente p1 WHERE p1.padre_id IS NULL ORDER BY p1.id";
    $raices = $conn->query($sql2);
    

    功能:

            function make_tree($resguardo, $root){
                $tree = [];
                $tree = $root;
                foreach ($resguardo[$root["id"]] as $node) {
                    add($tree, $node, $resguardo);
                }
                return $tree;
            }
    
            function add(&$root, &$children, $resguardo){
                $root["children"][$children["minor"]] = $children;
    
                $flag= false;
                if (isset($resguardo[$children["minor"]])) {
                    $flag = true;
                }
    
                if ($flag == false){
                    return;
                } else {
                    foreach ($resguardo[$children["minor"]] as $child) {
                        agregar($root["children"][$children["minor"]], $child, $resguardo);
                    }
                }
            }
    
            function preorder2(&$root) {
                if ($root) {
                    echo "<li>";
                    echo '<a href="">';
                    echo $root["name"];
                    echo "</a>";
    
                    if (array_key_exists("children", $root)) {
                        echo "<ul>";
                        foreach ($root["children"] as $c) {
                            preorder2($c);
                        }
                        echo "</ul>";
                    }
                    echo "</li>";
                }
            }
    

    我在这里称呼他们:

    while( $row = mysqli_fetch_assoc($result)){
        $resguardo[$row["id"]][] = $row;
    }
        while( $root = mysqli_fetch_assoc( $roots)){
        echo '<ul>';
        $tree = make_tree($resguardo, $root);
        preorder2($tree);
        echo "</ul>";
    } 
    

    非常感谢你们两位,如果没有你们的帮助,我永远不会解决它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-07-20
      相关资源
      最近更新 更多