【问题标题】:Finding Paths between Parent Node and specific Child Nodes in a Tree在树中查找父节点和特定子节点之间的路径
【发布时间】:2018-05-03 18:25:44
【问题描述】:

对于这个问题的开放式性质提前道歉,但我目前正在集思广益,使用 Python 解决自动化问题。我正在分析的一组数据可以被认为是一棵如下所示的树:

我的问题有两个部分,首先是棘手的部分,然后是更一般的实现问题。

  1. 对于给定的顶级父节点(没有父节点的节点),我如何仅针对集合中的底部节点找到到底部子节点(没有子节点的节点)的路径我定义的价值观?例如,如果我只将值集定义为“B”和“F”,我只想提取从 A 到 B 和 A 到 F 的路径。如,我应该得到 [A -> Y -> B] 和 [A -> Z -> C -> F] 作为答案。

  2. 鉴于上述要求,在 Python 中表示这些树的最佳方式是什么?我最初的想法是嵌套字典,其中每个节点都定义为字典键。请记住,我给出的示例很简单。我将为许多不同的顶级父级构建这些树,每个顶级父级可能有很多很多子节点。

【问题讨论】:

  • 请求节点的子集与总叶子集相比是否会非常小?如果不是(或者如果性能不是问题,因为树总是很小),您可以迭代所有叶子(使用简单的深度优先或广度优先搜索)并将其过滤为“这片叶子在想要的叶子?”
  • @abarnert 有道理,子集实际上将占总叶子的很大一部分,我不太担心性能。这是一种“一劳永逸”类型的脚本,只要它运行相对较快,遍历所有叶子就应该可以正常工作。

标签: python python-3.x tree


【解决方案1】:

假设所需叶子的数量与叶子的数量相同,最简单的解决方案是在 所有 路径上构建一个通用迭代器,然后在匹配项上对其进行过滤。例如:

def find_paths(self, targets):
    targets = set(targets)
    for path in self.iter_all_paths_dfs():
        if path[-1].name in targets:
            yield path

(当然,您可以将其浓缩为单个生成器表达式或 filter 调用,但我明确将其写出来以使其显而易见。)


如果你可以这样做,你就不需要反向指针或下一个指针,所以一个节点可以是一个将子名称映射到子节点的字典,正如你所建议的那样。

但是,将节点视为名称以及子节点的集合通常更简单。比较:

class Node(collections.namedtuple('Node', ('name', 'children'))):
    def iter_node_names_dfs(self):
        yield self.name
        for child in self.children:
            yield from child.iter_node_names_dfs()

E = Node('E', ())
F = Node('F', ())
C = Node('C', (E, F))
D = Node('D', ())
Z = Node('Z', (C, D))
X = Node('X', ())
A = Node('A', (X, Z))
tree = A

到:

E = {}
F = {}
C = {'E': {}, 'F': {}}
D = {}
Z = {'C': C, 'D': D}
X = {}
A = {'X': X, 'Z': Z}
tree = {'A': A}

def iter_node_names_dfs(tree):
    for name, child in tree.items():
        yield name
        yield from iter_node_names_dfs(child)

请注意,dict 解决方案需要一个额外的节点来指向 A,以便您可以保存其名称,这也意味着您无法从节点中获取节点的名称;您必须从上一步中记住它。

就空间而言,差别不大,但您当然可以进行测试(如果有问题,可以通过递归和总结 sys.getsizeof(node))。

【讨论】:

  • 太棒了!非常清晰的解释和实现很有意义。这为这个项目提供了一个很好的起点,感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多