树搜索 - 给定树中的两个节点,检查它们是否连接 - python
Tree Search - given two nodes in a tree, check if they are connected - python
给定一个搜索树,例如
"1"
└ "2"
├ "2.1"
┊ └ "3"
┊
└ "2.2"
└ "2.2.1"
└ "3"
以及属于该树的两个节点 a
和 b
,例如“2.1”和“3”。我们如何检查 a
和 b
是否是父子(或子父)相关/连接的?
对于第一个例子,应该产生True。这里还有一些:
a="3" b="1" -> False
a="3" b="2" -> False
a="2.2.1" b="2.2" -> True
a="2.2.1" b="3" -> True
我目前正在使用 anytree
library, with which I am struggling to implement this solution. The above graph is a structural simplification. What I have currently tried implementing is outlined here: https://pastebin.com/Mjk7gyqH
如果可以用纯 python 或任何树给出答案,那就太棒了,但任何答案都比 none 好。
您可以使用简单的递归:
tree = {'name': '1', 'children': [{'name': '2', 'children': [{'name': '2.1', 'children': [{'name': '3'}]}, {'name': '2.2', 'children': [{'name': '2.2.1', 'children': [{'name': '3'}]}]}]}]}
def in_tree(d, node):
return d['name'] == node or any(in_tree(i, node) for i in d.get('children', []))
def lookup(tree, a, b, flag=False):
if tree['name'] == b and flag:
return True
return any(lookup(j, a, b, tree['name'] == a) for j in tree.get('children', []))
test = [['3', '1'], ['3', '2'], ['2.2.1', '2.2'], ['2.2.1', '3'], ['60', '70']]
for a, b in test:
if not in_tree(tree, a) or not in_tree(tree, b):
raise AttributeError('Node(s) missing in tree')
print(any([lookup(tree, a, b), lookup(tree, b, a)]))
输出:
False
False
True
True
Traceback (most recent call last):
File "<stdin>", line 3, in <module>
AttributeError: Node(s) missing in tree
如果我理解得很好,你 'just' 要求没有任何中间节点的直接父子关系。
如果这不是您要查找的内容,请提供另一个示例,说明以下代码在哪里失败,我可以修复它。
代码使用 anytree,因为这是您建议的库
from anytree import Node, RenderTree
nodes = {} # a dict as a lookup to find nodes by name
def add_node(val, parentval=None):
if parentval is not None:
node = nodes[val] = Node(val, parent=nodes[parentval])
else:
node = nodes[val] = Node(val)
return node
def mk_tree():
top = add_node("1")
add_node("2", "1")
add_node("2.1", "2")
add_node("3", "2.1")
add_node("2.2", "2")
add_node("2.2.1", "2.2")
add_node("3", "2.2.1")
return top
def is_child_or_parent(n1, n2):
return n1.parent == n2 or n2.parent == n1
testpatterns = [
("3", "1", False),
("3", "2", False),
("2.2.1", "2.2", True),
("2.2.1", "3", True),
]
def run_test():
for name1, name2, expected in testpatterns:
node1 = nodes[name1]
node2 = nodes[name2]
rslt = is_child_or_parent(node1, node2)
print(node1, node2, expected, rslt)
assert rslt == expected
tree = mk_tree()
print(RenderTree(tree))
run_test()
给定一个搜索树,例如
"1"
└ "2"
├ "2.1"
┊ └ "3"
┊
└ "2.2"
└ "2.2.1"
└ "3"
以及属于该树的两个节点 a
和 b
,例如“2.1”和“3”。我们如何检查 a
和 b
是否是父子(或子父)相关/连接的?
对于第一个例子,应该产生True。这里还有一些:
a="3" b="1" -> False
a="3" b="2" -> False
a="2.2.1" b="2.2" -> True
a="2.2.1" b="3" -> True
我目前正在使用 anytree
library, with which I am struggling to implement this solution. The above graph is a structural simplification. What I have currently tried implementing is outlined here: https://pastebin.com/Mjk7gyqH
如果可以用纯 python 或任何树给出答案,那就太棒了,但任何答案都比 none 好。
您可以使用简单的递归:
tree = {'name': '1', 'children': [{'name': '2', 'children': [{'name': '2.1', 'children': [{'name': '3'}]}, {'name': '2.2', 'children': [{'name': '2.2.1', 'children': [{'name': '3'}]}]}]}]}
def in_tree(d, node):
return d['name'] == node or any(in_tree(i, node) for i in d.get('children', []))
def lookup(tree, a, b, flag=False):
if tree['name'] == b and flag:
return True
return any(lookup(j, a, b, tree['name'] == a) for j in tree.get('children', []))
test = [['3', '1'], ['3', '2'], ['2.2.1', '2.2'], ['2.2.1', '3'], ['60', '70']]
for a, b in test:
if not in_tree(tree, a) or not in_tree(tree, b):
raise AttributeError('Node(s) missing in tree')
print(any([lookup(tree, a, b), lookup(tree, b, a)]))
输出:
False
False
True
True
Traceback (most recent call last):
File "<stdin>", line 3, in <module>
AttributeError: Node(s) missing in tree
如果我理解得很好,你 'just' 要求没有任何中间节点的直接父子关系。 如果这不是您要查找的内容,请提供另一个示例,说明以下代码在哪里失败,我可以修复它。
代码使用 anytree,因为这是您建议的库
from anytree import Node, RenderTree
nodes = {} # a dict as a lookup to find nodes by name
def add_node(val, parentval=None):
if parentval is not None:
node = nodes[val] = Node(val, parent=nodes[parentval])
else:
node = nodes[val] = Node(val)
return node
def mk_tree():
top = add_node("1")
add_node("2", "1")
add_node("2.1", "2")
add_node("3", "2.1")
add_node("2.2", "2")
add_node("2.2.1", "2.2")
add_node("3", "2.2.1")
return top
def is_child_or_parent(n1, n2):
return n1.parent == n2 or n2.parent == n1
testpatterns = [
("3", "1", False),
("3", "2", False),
("2.2.1", "2.2", True),
("2.2.1", "3", True),
]
def run_test():
for name1, name2, expected in testpatterns:
node1 = nodes[name1]
node2 = nodes[name2]
rslt = is_child_or_parent(node1, node2)
print(node1, node2, expected, rslt)
assert rslt == expected
tree = mk_tree()
print(RenderTree(tree))
run_test()