繁体   English   中英

使用 PHP 计算 MySQL 中分层(树)数据结构中节点的所有子节点

[英]Count all Children of Nodes in a Hierarchical (Tree) Data Structure in MySQL using PHP

我想计算树结构任何级别中所有子级的数量。 树不是二元的,因此一个节点可以有 2 个以上的子节点。 现在我已经创建了一个递归函数来完成这项工作,但它真的很慢。 我需要一种更快的方法,但我不能以任何其他方式做到。

所以,假设我们有那个表:

NodeID |  ParentID
-------------------
  1    |     0
  2    |     1
  3    |     1
  4    |     2
  5    |     1
  6    |     2
  7    |     3
  8    |     5
  9    |     6
 10    |     8
 11    |     6
 11    |     6
• 1
  • 2
    • 4
    • 6
      • 9
      • 11
      • 12
  • 3
    • 7
  • 5
    • 8
      • 10

因此,如果我想获取节点 1 的子节点数,则该数字应为 11 而不是 3。节点 2 也是如此。数字应为 5 而不是 2。

这是我在 PHP 中创建的递归函数,但它很慢:

function count_all_nodes($connection, $element_id, $elements=false, $i=0) {
    if (!$elements) {
        $result = mysqli($connection, "SELECT `node_id`, `parent_id` FROM `elements`");

        while ($row = mysqli_fetch_array($result)) {
            $sub_elements["node_id"] = $row["node_id"];
            $sub_elements["parent_id"] = $row["parent_id"];
            $elements[] = $sub_elements;
        }
    }

    foreach ($elements as $element) {
        if ($element["parent_id"] == $element_id) {
            $i++;
            $i += count_all_nodes($connection, $element_id, $elements);
        }
    }

    return $i;
}

有什么办法可以避免这个递归函数吗?

谢谢!

我认为分层数据结构(树)是递归的同义词。

我在 php 中实现了两个递归函数,它们可能比您的代码更快,因为我只执行一个 MySql 查询来获取树信息,而不是像您一样在每次调用递归函数时执行一个。

示例数据:

在此处输入图片说明

根节点(树的第一个节点)没有父亲,我将此设置指示到其父亲字段“0-A”(此节点不存在)中,但您可以将其设为 null。

要获取树信息,我执行此查询:

SELECT node, father
FROM tree
ORDER BY node;

我在 php 中得到这样的东西:

$nodes = array ( 0 => array ( 'node' => '1-A', 'father' => '0-A', ), 1 => array ( 'node' => '2-A', 'father' => '1-A', ), 2 => array ( 'node' => '3-A', 'father' => '1-A', ), 3 => array ( 'node' => '4-A', 'father' => '2-A', ), 4 => array ( 'node' => '5-A', 'father' => '2-A', ), 5 => array ( 'node' => '6-A', 'father' => '3-A', ), 6 => array ( 'node' => '7-A', 'father' => '3-A', ), 7 => array ( 'node' => '9-A', 'father' => '6-A', ), 8 => array ( 'node' => '10-A', 'father' => '7-A', ), 9 => array ( 'node' => '8-A', 'father' => '7-A', ), 10 => array ( 'node' => '11-A', 'father' => '10-A', ), )

这是我的php代码:

/**
 * Count all Children of each node in a Hierarchical Data Structure (Tree).
 *
 * @param array(idNode => idNodeFather) $nodes
 * @param string $actualNode
 * @param array(idDode => totalChildrens) $result
 */
function countChildrensNode($nodes, $actualNode, &$result) {
    foreach($nodes as $node => $father) {
        if($actualNode == $father) {
            $result[$father]++;
            countChildrensNode($nodes, $node, $result);
            incrementActualNodeAncestor($nodes, $father, $result);
        }
    }
}

/**
 * Increment by one to all actual node's ancestors.
 *
 * @param array(idNode => idNodeFather) $nodes
 * @param string $actualNode
 * @param array(idDode => totalChildrens) $result
 */
function incrementActualNodeAncestor($nodes, $actualNode, &$result) {
    foreach($nodes as $node => $father) {
        if($actualNode == $node) {
            if($father != '0-A' && ! is_null($father)) {
                $result[$father]++;
                incrementActualNodeAncestor($nodes, $father, $result);
            }
        }
    }
}

//$nodes is the array return by my query.
$nodesfathers = array_combine (array_column($nodes, "node"), array_column($nodes, "father"));
$res = array_fill_keys(array_column($nodes, "node"), 0);

countChildrensNode($nodesfathers, array_keys($nodesfathers)[0], $res);

countChildrensNode 函数向前搜索(将实际节点的父亲递增 1 并调用 incrementActualNodeAncestor 第二个递归函数)和 incrementActualNodeAncestor 向后查找(并且将实际节点的每个祖先递增 1)。

结果在 $res var 中:

'1-A' 10
'2-A' 2
'3-A' 6
'4-A' 0
'5-A' 0
'6-A' 1
'7-A' 3
'9-A' 0
'10-A' 1
'8-A' 0
'11-A' 0

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM