为此问题的开放性质提前道歉,但我目前正在集思广益,使用Python解决自动化问题。我正在分析的一组数据可以被认为是一棵如下所示的树:
我的问题分为两部分,第一部分是棘手的部分,然后是更多的一般性实施问题。
对于给定的顶级父节点(没有父节点的节点),如何找到底层子节点(没有子节点的节点)的路径仅适用于集合中的底层节点我定义的值?例如,如果我将值集定义为“B”和“F”,我只想提取从A到B和A到F的路径。就像在,我应该得到[A - >; Y - > B]和[A - > Z - > C - > F]作为答案。
鉴于上述要求,在Python中表示这些树的最佳方法是什么?我最初的想法是嵌套字典,其中每个节点都被定义为字典键。请记住,我给出的例子很简单。我将为许多不同的顶级父母构建这些树,每个顶级父级可能有许多子节点。
答案 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)
,如果这是一个问题)。