查找父节点与树中特定子节点之间的路径

时间:2018-05-03 18:25:44

标签: python python-3.x tree

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

Example of Tree Structure

我的问题分为两部分,第一部分是棘手的部分,然后是更多的一般性实施问题。

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

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

1 个答案:

答案 0 :(得分:0)

假设所需叶子的数量与叶子数量的顺序相同,最简单的解决方案就是在所有路径上构建通用迭代器,然后在匹配时过滤它。例如:

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调用,但我明确地将其写出来以使其显而易见。)

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

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

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),如果这是一个问题)。