Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/280.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_Algorithm_Tree - Fatal编程技术网

Php 如何从递归树中列出所有可能性?

Php 如何从递归树中列出所有可能性?,php,algorithm,tree,Php,Algorithm,Tree,我得到了这些初始数据: $h = [ 'id' => 'h', 'name' => 'H', 'config' => [], ]; $g = [ 'id' => 'g', 'name' => 'G', 'config' => [], ]; $f = [ 'id' => 'f', 'name' => 'F', 'config' => [ [

我得到了这些初始数据:

$h = [
    'id' => 'h',
    'name' => 'H',
    'config' => [],
];

$g = [
    'id' => 'g',
    'name' => 'G',
    'config' => [],
];

$f = [
    'id' => 'f',
    'name' => 'F',
    'config' => [
        [
            ['id' => $g['id'], 'quantity' => 1],
        ],
        [
            ['id' => $h['id'], 'quantity' => 2],
        ],
    ],
];

$e = [
    'id' => 'e',
    'name' => 'E',
    'config' => [],
];

$d = [
    'id' => 'd',
    'name' => 'D',
    'config' => [
        [
            ['id' => $e['id'], 'quantity' => 1],
            ['id' => $f['id'], 'quantity' => 3],
        ],
    ],
];

$c = [
    'id' => 'c',
    'name' => 'C',
    'config' => [
        [
            ['id' => $f['id'], 'quantity' => 1],
        ],
        [
            ['id' => $e['id'], 'quantity' => 1],
        ],
    ],
];

$b = [
    'id' => 'b',
    'name' => 'B',
    'config' => [
        [
            ['id' => $c['id'], 'quantity' => 1],
        ],
    ],
];

$a = [
    'id' => 'a',
    'name' => 'A',
    'config' => [
        [
            ['id' => $d['id'], 'quantity' => 1],
        ],
        [
            ['id' => $b['id'], 'quantity' => 1],
        ],
    ],
];
我将解释“配置”是如何工作的:

  • 这是一系列的可能性(或)=>例如,从$c我们可以得到$f或$e
  • 在这些可能性中有一个AND=>数组,例如,从$d开始,我们只有一个可能性是$e和$f
  • 当配置为空时,它是一个叶子,因此我们可以停止
  • 而棘手的部分(我认为)是,我们可以在每个配置中有数量,这意味着从$f开始,我们可以有$g一次或$h两次从$d开始,我们有$e一次和$f三次
我希望通过我的算法实现如下输出:

$possibilities = [
    [
        [
            'id' => 'a',
            ...
        ],
        [
            'id' => 'b',
            'parent' => 'a',
            ...
        ],
        [
            'id' => 'c',
            'parent' => 'b',
            ...
        ],
        [
            'id' => 'f',
            'parent' => 'c'
        ]
    ],
    [
        [
            'id' => 'a',
            ...
        ],
        [
            'id' => 'b',
            'parent' => 'a',
            ...
        ],
        [
            'id' => 'c',
            'parent' => 'b',
            ...
        ],
        [
            'id' => 'e',
            'parent' => 'c'
        ]
    ],
    [
        [
            'id' => 'a',
            ...
        ],
        [
            'id' => 'd',
            'parent' => 'a',
            ...
        ],
        [
            'id' => 'e',
            'parent' => 'd',
            ...
        ],
        [
            'id' => 'f-1',
            'parent' => 'd',
            ...
        ],
        [
            'id' => 'f-2',
            'parent' => 'd',
            ...
        ],
        [
            'id' => 'f-3',
            'parent' => 'd',
            ...
        ],
        [
            'id' => 'g',
            'parent' => 'f-1',
            ...
        ],
        [
            'id' => 'g',
            'parent' => 'f-2',
            ...
        ],
        [
            'id' => 'g',
            'parent' => 'f-3',
            ...
        ]
    ],
    ...
];
global $datas;
$datas = compact($a, $b, $c, $d, $e, $f, $g, $h);

function formatTree($tree)
{
    if (empty($tree['config'])) {
        return [$tree];
    }

    $config = $tree['config'];
    unset($tree['config']);

    $tree2 = [$tree];

    foreach ($config as $item) {
        $sub = formatTree($item);
        $tree2 = array_merge($tree2, $sub);
    }

    return $tree2;
}


function preparePossibilities($item)
{
    $possibilities = [];

    if (empty($item['config'])) {
        return [$item];
    }

    $config = $item['config'];
    unset($item['config']);

    foreach ($config as $or) {
        $finalOr = [];
        foreach ($or as $and) {
            for ($i = 0; $i < ($and['quantity'] ?? 1); $i++) {
                $finalOr[] = $and;
            }
        }
        $item['config'] = $finalOr;
        $possibilities[] = $item;
    }

    return $possibilities;
}

function are_same($trees)
{
    $id = null;
    foreach ($trees as $tree) {
        $oldId = $id;
        $id = $tree[0]['id'];
        if (isset($oldId) && $oldId !== $id) {
            return false;
        }
    }

    return true;
}

function getAllTrees($id)
{
    global $datas;
    $data = current(array_filter($datas, static function ($d) use ($id) {
        return $d['id'] === $id;
    }));

    $multiplePossibilities = preparePossibilities($data);

    $allTrees = [];

    foreach ($multiplePossibilities as $possibility) {
        if (empty($possibility['config'])) {
            return [$possibility];
        }

        $config = $possibility['config'];
        unset($possibility['config']);

        $trees = [];
        foreach ($config as $i => $and) {
            $subTrees = getAllTrees($and['id']);

            foreach ($subTrees as $subTree) {
                $trees[$i][] = $subTree;
            }

        }

        $trees = array_values($trees);

        if (count($trees) === 1) {
            foreach ($trees as $tree) {
                foreach ($tree as $t) {
                    $newP = $possibility;
                    $newP['config'] = [];
                    $newP['config'][] = $t;
                    $allTrees[] = $newP;
                }
            }
        } elseif (are_same($trees)) {
            $newP = $possibility;
            $newP['config'] = $trees;
            $allTrees[] = $newP;
        } else {
            $newP = $possibility;
            $newP['config'] = [];
            foreach ($trees as $tree) {
                if (count($tree) === 1) {
                    $newP['config'][] = $tree[0];
                } else {
                    foreach ($tree as $t) {
                        $p3 = $newP;
                        $p3['config'][] = $t;
                        $allTrees[] = $p3;
                    }
                }
            }
        }

    }

    return $allTrees;
}

foreach (getAllTrees('a') as $tree) {
    var_dump(formatTree($tree));
}
因此,我想提取并列出任何可能性,以及父节点(如果数量>1,则包括其编号) 到目前为止,我已经尝试过这样的方法:

$possibilities = [
    [
        [
            'id' => 'a',
            ...
        ],
        [
            'id' => 'b',
            'parent' => 'a',
            ...
        ],
        [
            'id' => 'c',
            'parent' => 'b',
            ...
        ],
        [
            'id' => 'f',
            'parent' => 'c'
        ]
    ],
    [
        [
            'id' => 'a',
            ...
        ],
        [
            'id' => 'b',
            'parent' => 'a',
            ...
        ],
        [
            'id' => 'c',
            'parent' => 'b',
            ...
        ],
        [
            'id' => 'e',
            'parent' => 'c'
        ]
    ],
    [
        [
            'id' => 'a',
            ...
        ],
        [
            'id' => 'd',
            'parent' => 'a',
            ...
        ],
        [
            'id' => 'e',
            'parent' => 'd',
            ...
        ],
        [
            'id' => 'f-1',
            'parent' => 'd',
            ...
        ],
        [
            'id' => 'f-2',
            'parent' => 'd',
            ...
        ],
        [
            'id' => 'f-3',
            'parent' => 'd',
            ...
        ],
        [
            'id' => 'g',
            'parent' => 'f-1',
            ...
        ],
        [
            'id' => 'g',
            'parent' => 'f-2',
            ...
        ],
        [
            'id' => 'g',
            'parent' => 'f-3',
            ...
        ]
    ],
    ...
];
global $datas;
$datas = compact($a, $b, $c, $d, $e, $f, $g, $h);

function formatTree($tree)
{
    if (empty($tree['config'])) {
        return [$tree];
    }

    $config = $tree['config'];
    unset($tree['config']);

    $tree2 = [$tree];

    foreach ($config as $item) {
        $sub = formatTree($item);
        $tree2 = array_merge($tree2, $sub);
    }

    return $tree2;
}


function preparePossibilities($item)
{
    $possibilities = [];

    if (empty($item['config'])) {
        return [$item];
    }

    $config = $item['config'];
    unset($item['config']);

    foreach ($config as $or) {
        $finalOr = [];
        foreach ($or as $and) {
            for ($i = 0; $i < ($and['quantity'] ?? 1); $i++) {
                $finalOr[] = $and;
            }
        }
        $item['config'] = $finalOr;
        $possibilities[] = $item;
    }

    return $possibilities;
}

function are_same($trees)
{
    $id = null;
    foreach ($trees as $tree) {
        $oldId = $id;
        $id = $tree[0]['id'];
        if (isset($oldId) && $oldId !== $id) {
            return false;
        }
    }

    return true;
}

function getAllTrees($id)
{
    global $datas;
    $data = current(array_filter($datas, static function ($d) use ($id) {
        return $d['id'] === $id;
    }));

    $multiplePossibilities = preparePossibilities($data);

    $allTrees = [];

    foreach ($multiplePossibilities as $possibility) {
        if (empty($possibility['config'])) {
            return [$possibility];
        }

        $config = $possibility['config'];
        unset($possibility['config']);

        $trees = [];
        foreach ($config as $i => $and) {
            $subTrees = getAllTrees($and['id']);

            foreach ($subTrees as $subTree) {
                $trees[$i][] = $subTree;
            }

        }

        $trees = array_values($trees);

        if (count($trees) === 1) {
            foreach ($trees as $tree) {
                foreach ($tree as $t) {
                    $newP = $possibility;
                    $newP['config'] = [];
                    $newP['config'][] = $t;
                    $allTrees[] = $newP;
                }
            }
        } elseif (are_same($trees)) {
            $newP = $possibility;
            $newP['config'] = $trees;
            $allTrees[] = $newP;
        } else {
            $newP = $possibility;
            $newP['config'] = [];
            foreach ($trees as $tree) {
                if (count($tree) === 1) {
                    $newP['config'][] = $tree[0];
                } else {
                    foreach ($tree as $t) {
                        $p3 = $newP;
                        $p3['config'][] = $t;
                        $allTrees[] = $p3;
                    }
                }
            }
        }

    }

    return $allTrees;
}

foreach (getAllTrees('a') as $tree) {
    var_dump(formatTree($tree));
}

好吧,如果我是你,我会开始分解问题,简化测试数据,然后让它变得更复杂。您还可以创建一个节点类,该类能够添加其他节点并打印其子节点。关于2f或1g等的计数。这只是一个选项数组,你可以做一个基本的for循环,不是吗?筛选所有选项。每次你添加另一个节点。谢谢你的回复,我会试试你的建议!我已经试着打破,但在某个时候,当更复杂的时候,我无法让它工作。。。但是我会尝试node类并在options上循环。如果我是你,我会开始解决这个问题,简化测试数据,然后随着时间的推移使它变得更复杂。您还可以创建一个节点类,该类能够添加其他节点并打印其子节点。关于2f或1g等的计数。这只是一个选项数组,你可以做一个基本的for循环,不是吗?筛选所有选项。每次你添加另一个节点。谢谢你的回复,我会试试你的建议!我已经试着打破,但在某个时候,当更复杂的时候,我无法让它工作。。。但我将尝试node类和循环选项