Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/css/37.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 递归。每个树枝的最大元素数_Php_Recursion - Fatal编程技术网

Php 递归。每个树枝的最大元素数

Php 递归。每个树枝的最大元素数,php,recursion,Php,Recursion,我有一个构建递归菜单树的类。数据选择来自以下字段的数据库:id,title,id\u parent class Menu { private $db; private $menus_arr = []; public function __construct() { $this->db = new PDO('mysql:host=localhost; dbname=test', 'root', 'admin'); $this->menus_arr = $this-

我有一个构建递归菜单树的类。数据选择来自以下字段的数据库:
id
title
id\u parent

class Menu {

private $db;
private $menus_arr = [];

public function __construct() 
{
    $this->db = new PDO('mysql:host=localhost; dbname=test', 'root', 'admin');
    $this->menus_arr = $this->getMenus();
    echo "<pre>";
    print_r($this->menus_arr);
    echo "</pre>";
}

private function getMenus() 
{
    $query = $this->db->prepare("SELECT * FROM menu");
    $query->execute();
    $result = $query->fetchAll(PDO::FETCH_ASSOC);

    // делаем из одномерного массива двумерный, в котором первый ключ - id_parent
    $arr = [];
    foreach ($result as $value) {
        $arr[$value['id_parent']][] = $value;
    }
    return $arr;
}

public function makeTree($id_parent = 0, $lvl = 0) 
{

    if (isset($this->menus_arr[$id_parent])) { 
        foreach ($this->menus_arr[$id_parent] as $value) {
            echo "<div class='test' style='margin: 5px 0 5px " . ($lvl * 30) . "px;'>$lvl - " . $value['title'] . "</div>"; 
            $lvl++;
            $this->makeTree($value['id'], $lvl); 
            $lvl--; 
        }
    }
}
表结构:

打印的递归树:


如何确定每个分支的最后一个元素?

我们可以通过SQL实现。我们应该使用窗口函数来确定树的最后一个元素

根据您在评论中所写的内容,这是目前最好的猜测:


这是作业还是实际测试?它没有子项?我需要解决这个问题是的,所选元素没有子项,所以您需要单独在php中执行此操作?另一个问题,为什么(例如)
“子菜单2”
不算作叶节点?它也没有孩子。我需要通过makeTree()方法完成。谢谢你,Yoshi。这正是我想做的。虽然,不完全正确。已添加到数组['id'=>19,'title'=>m:1.1.3.1','id\u parent'=>7],'id'=>20,'title'=>m:1.1.3.1.1','id\u parent'=>19]@用户381403我更改了答案。它现在计算给定根的最大深度,以便在显示节点时使用。谢谢,Yoshi。
$tree = new Menu();
$tree->makeTree();
<?php
class Menu
{
    private $menus_arr = [];

    public function __construct()
    {
        $this->menus_arr = $this->getMenus();
    }

    private function getMenus()
    {
        // substitute db access
        $result = [
            ['id' =>  1, 'title' => 'm: 1',            'id_parent' =>  0],
            ['id' =>  2, 'title' => 'm: 1.1',          'id_parent' =>  1],
            ['id' =>  3, 'title' => 'm: 1.1.1',        'id_parent' =>  2],
            ['id' =>  4, 'title' => 'm: 1.1.1.1',      'id_parent' =>  3],
            ['id' =>  5, 'title' => 'm: 1.1.1.2',      'id_parent' =>  3],
            ['id' =>  6, 'title' => 'm: 1.1.2',        'id_parent' =>  2],
            ['id' =>  7, 'title' => 'm: 1.1.3',        'id_parent' =>  2],
            ['id' => 19, 'title' => 'm: 1.1.3.1',      'id_parent' =>  7],
            ['id' => 20, 'title' => 'm: 1.1.3.1.1',    'id_parent' => 19],
            ['id' =>  8, 'title' => 'm: 1.2',          'id_parent' =>  1],
            ['id' =>  9, 'title' => 'm: 1.3',          'id_parent' =>  1],
            ['id' => 10, 'title' => 'm: 2',            'id_parent' =>  0],
            ['id' => 11, 'title' => 'm: 2.1',          'id_parent' => 10],
            ['id' => 12, 'title' => 'm: 2.1.1',        'id_parent' => 11],
            ['id' => 13, 'title' => 'm: 2.1.1.1',      'id_parent' => 12],
            ['id' => 14, 'title' => 'm: 2.1.2',        'id_parent' => 11],
            ['id' => 15, 'title' => 'm: 2.2',          'id_parent' => 10],
            ['id' => 16, 'title' => 'm: 2.3',          'id_parent' => 10],
            ['id' => 17, 'title' => 'm: 2.3.1',        'id_parent' => 16],
            ['id' => 18, 'title' => 'm: 2.3.1.1',      'id_parent' => 17],
        ];

        $arr = [];
        foreach ($result as $value) {
            $arr[$value['id_parent']][] = $value;
        }

        return $arr;
    }

    public function makeTree()
    {
        foreach ($this->menus_arr[0] as $root) {
            $this->renderNode($root, 0, $this->getMaxDepth($root));
        }
    }

    /**
     * @param array $node
     * @param int   $depth
     * @param int   $maxDepth
     */
    private function renderNode(array $node, $depth = 0, $maxDepth = 0)
    {
        printf(
            '<div class="test" style="margin: 5px 0 5px %dpx">%s - %s%s</div>',
            $depth * 30,
            $depth,
            $node['title'],
            $depth === $maxDepth ? '&lt;--' : ''
        );

        if (isset($this->menus_arr[$node['id']])) {
            foreach ($this->menus_arr[$node['id']] as $child) {
                $this->renderNode($child, $depth + 1, $maxDepth);
            }
        }
    }

    /**
     * @param array $root
     *
     * @return int
     */
    private function getMaxDepth(array $root)
    {
        $result = 0;

        if (isset($this->menus_arr[$root['id']])) {
            foreach ($this->menus_arr[$root['id']] as $child) {
                $result = max($result, $this->getMaxDepth($child) + 1);
            }
        }

        return $result;
    }
}

$tree = new Menu();
$tree->makeTree();