我有一个树形网络,我想在其中找到“生成”这一代。所有父节点(见下文)。
所有父节点都有两个孩子。
这在列表中显示为:
parents = [ 2, 3, 1, 5, 4, 7, 8, 9, 6, 10 ]
children = [ [4,5], [0,11], [6,10] [1,7] [8,9] [12,13], [14,15], [16,17], [18,19], [20,21] ]
因此,例如父节点' 2'有直接的子节点[4,5]。
我将父节点的生成定义为没有子节点的节点的最长路径。例如,对于父节点' 2'有一些没有孩子的节点有许多不同的路由,例如。
1)2 - > 4 - > 9 - > 17
2)2 - > 5 - > 1 - > 10 - > 21
由于第二条路线是较长的路线,所以父母的第二条路线就会生成2'是4,因为需要4个节点才能到达' 21'和' 21'是一个叶子节点。
因此,在这种情况下使用parents
列表,我想要的结果是:
generation = [4, 1, 2, 3, 2, 1, 1, 1, 1, 1]
其中generation
列表的每个索引都对应parents
列表中节点的生成。
如何从parents
和children
列表中获取生成列表?
答案 0 :(得分:3)
这是一个单线解决方案,但不太高效:
parents = [ 2, 3, 1, 5, 4, 7, 8, 9, 6, 10 ]
children = [ [4,5], [0,11], [6,10], [1,7], [8,9], [12,13], [14,15], [16,17], [18,19], [20,21] ]
generation=[(lambda f,*x:f(f,*x))(lambda g,i,c:max(g(g,j,c)+1for j in c[i])if i in c else 0,i,dict(zip(parents,children)))for i in parents]
print(generation)
PS:您提供的父母和子集数组定义缺少一些逗号。
<强>更新强>
这是高性能版本,具有memoized递归:
parents = [ 2, 3, 1, 5, 4, 7, 8, 9, 6, 10 ]
children = [ [4,5], [0,11], [6,10], [1,7], [8,9], [12,13], [14,15], [16,17], [18,19], [20,21] ]
generation=(lambda c:list(map((lambda f,m={}:lambda x:m[x]if x in m else m.setdefault(x,f(f,x)))(lambda g,i:max(g(g,j)+1for j in c[i])if i in c else 0),parents)))(dict(zip(parents,children)))
print(generation)
答案 1 :(得分:1)
虽然有一个简洁的解决方案可以计算每个节点的生成,但您还可以实现跟踪每个节点生成的树数据结构。
class Forest:
def __init__(self, forest_dict):
self.trees = [Tree(value, children) for value, children in forest_dict.items()]
def __iter__(self):
for tree in self.trees:
for node in iter(tree):
yield node
class Tree:
def __init__(self, value, children):
self.root = node = Node(value)
self.__recurse(node, children)
def __recurse(self, node, children):
for value, subchildren in children.items():
child = Node(value, node)
node.addChild(child)
self.__recurse(child, subchildren)
def __iter__(self):
for node in iter(self.root):
yield node
class Node:
def __init__(self, value, parent=None):
self.value = value
self.parent = parent
self.children = []
self.generation = 0
def addChild(self, child):
if not self.children:
node, generation = self, 1
while node is not None:
node.generation = max(node.generation, generation)
generation += 1
node = node.parent
self.children.append(child)
def __iter__(self):
yield self
for child in self.children:
for subchild in iter(child):
yield subchild
然后,如果您将林区构建为嵌套字典,则很容易获得父节点代的列表。
forest_dict = {2:
{4:
{8:
{14: {},
15: {}
},
9: {16: {},
17: {}
}
},
5:
{1:
{6:
{18: {},
19: {}
},
10:
{20: {},
21: {}
}
},
7:
{12: {},
13: {}
}
}
},
3:
{0: {},
11: {}
}
}
forest = Forest(forest_dict)
print [node.generation for node in forest if node.generation]
# [4, 2, 1, 1, 3, 2, 1, 1, 1, 1]
显然,这还有很多工作要做,但根据你的工作情况,这可能是值得的。请注意,自字典和不同结构以来,顺序并不完全相同。