【问题标题】:Flat BOM structure to hierarchical, detecting cycles in your tree / graph平面 BOM 结构到分层,检测树/图中的循环
【发布时间】:2018-11-19 04:25:36
【问题描述】:

我有许多许多存储物料清单层次结构数据的表,例如:

标识 |孩子身份

一个 | b

一个 | c

c | d

d |一个

我需要找到闭环,例如在本例中 d 指向 a,这会破坏系统,因为某些递归函数永远不会停止。

我的想法是将这种数据结构从平面转换为分层结构,然后使用递归迭代分层结构。

我正在查找一些关于Web的知识以及将平面结构转换为嵌套结构的大多数解决方案,涵盖了以下情况:

标识 |父母身份

结构,其中顶级项目将parentId 设置为根值(例如零)。

多年来,我一直是一名自学成才的系统开发人员,但现在我缺乏你们许多人在学习期间所受的教育:)

编辑:图形示例

Valid trees:
a)
      A              
     / \             
    B   C               
         \
          D
         / \
        E   F

b)

      K -> E
     / \
    G   B
   /|\ 
  H I J


Invalid tree (closed loop)
      A             
     / \ 
    B   C<----\
         \     |
          D   /
         / \ /
        E   F
             \
              G
             /|\
            H I J

【问题讨论】:

  • 确实很有趣,但就我而言,它不是链接列表,而是树。

标签: php hierarchy hierarchical-data hierarchical flat


【解决方案1】:

经过一番反复试验,这是我想出的。

给定关系的平面列表,它会构建查找,然后将其用于递归遍历函数。遍历函数“记住”请求的原始部分 ($initialPart) 并在检测到循环时抛出异常。 例如。例外:Loop detected: f=&gt;c=&gt;d=&gt;f!

脚本:

$rows = [
    ['assemblyId' => 'a', 'partId' => 'b'],
    ['assemblyId' => 'a', 'partId' => 'c'],
    ['assemblyId' => 'c', 'partId' => 'd'],
    ['assemblyId' => 'd', 'partId' => 'e'],
    ['assemblyId' => 'd', 'partId' => 'f'],
    ['assemblyId' => 'f', 'partId' => 'c'],
    ['assemblyId' => 'f', 'partId' => 'g'],
    ['assemblyId' => 'g', 'partId' => 'h'],
    ['assemblyId' => 'g', 'partId' => 'i'],
    ['assemblyId' => 'g', 'partId' => 'j'],
];

$assemblyLookup = [];
foreach ($rows as $row) {
    $assemblyLookup[$row['assemblyId']][$row['partId']] = $row;
}

function getTree(&$part, $initialPart = null, $path = '', $level = 0, $maxLevel = 100) {
    global $assemblyLookup;

    if ($initialPart === null) {
        $initialPart = $part;
    }

    if ($level >= $maxLevel) {
        return;
    }

    $path .= '=>' . $part['partId'];
    if (is_array($assemblyLookup[$part['partId']])) {
        $lookup = $assemblyLookup[$part['partId']];
        foreach ($lookup as $child) {

            if ($child['partId'] === $initialPart['partId']) {
                $circularPath = substr($path, 2) . '=>' . $child['partId'] . '!';
                throw new Exception("Loop detected: " . $circularPath);
                return;
            }

            $part['children'][$child['partId']] = $child;
            getTree($part['children'][$child['partId']], $initialPart, $path, ++$level, $maxLevel);
        }
    } else {
        $path .= ';';
        $part['path'] = substr($path, 2); // Strip arrow from left side
    }

    return $part;

}

$part = ['partId' => 'f'];

$tree = getTree($part);

【讨论】:

    猜你喜欢
    • 2016-10-26
    • 2013-01-22
    • 2018-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多