如何解决在没有递归的情况下找到到达一定深度的所有路径中n元树的所有唯一节点
我正在尝试用Python编写算法,以获取路径到达特定深度的树中所有节点的唯一列表。
- 每个孩子在遍历之前有未知数目的孩子
- 可以通过可迭代的方式(例如
for child in B.get_children()
)访问子级
例如,请参见此树(应包括星号标记节点):
A*
|
-----
| |
B* C*
| |
| ---
| | |
D* E F*
/ | \ | \
G* H* I* J* K*
|
L
比方说,我试图达到3的深度。我需要一个能够以任意顺序产生序列[G,H,I,J,K,D,F,B,C,A]
的函数。
请注意:
-
E
(深度不超过3) -
L
(深度超过3)
我觉得有一种方法可以递归获取此列表。类似于:
def iterate_tree(path: List[T],all_nodes: Set[T]):
if len(path) == 4:
for node in path:
if node not in all_nodes:
all_nodes.add(node)
yield node
else:
for node in path[-1].get_children():
path = path.copy()
path.append(node)
yield from iterate_tree(path,all_nodes)
iterate_tree([A],set())
我不知道上面的方法是否有效,但是我认为可以从中破解。对于(可能不正确的)解决方案,我不满意的是:
- 递归:我正在写这个未知的深度。我不要堆栈溢出。
- 我真的觉得必须有一种方法可以在不携带
set
个先前的yielded
个节点的情况下进行此操作。 - 我必须在每次迭代时复制
path
的副本,以免弄乱递归的其他分支。
有什么建议吗?
解决方法
对于第1点,您可以使用显式堆栈循环而不是递归。
对于第二点,我不确定保留一组屈服节点是否存在问题。内存很便宜,如果您需要检测重复的内存,那么每次生成树时都要遍历树非常昂贵。
此外,您的实现基于节点哈希性检查唯一性,但是还不清楚节点如何计算其哈希。我假设您为此使用Node.val
。如果您基于对象引用进行哈希处理,则“唯一性”似乎毫无意义,因为可以确保节点对象树按身份是唯一的。此处的示例并未显示出唯一性的冲突。我的实现假定散列是对象身份(应该是对象身份),并且您可以使用Node.val
单独访问唯一性值。
对于第3点,如果您是递归工作,则无需复制路径列表,因为您可以重新访问调用框架并可以在单个列表上追加/弹出。迭代地,您可以在parent_of
集旁边保留一个nodes_yielded
字典,该集合保留对每个节点的父节点的引用。当我们到达所需深度的节点时,我们可以遍历此字典中的链接来重建路径,而不必担心多次使用nodes_yielded
重新访问分支。第二组vals_yielded
可用于对收益率实施唯一性。
最后,我真的不知道您的数据结构是什么,因此为了minimal,complete example的利益,我提供了一些适合您的内容。
import collections
def unique_nodes_on_paths_to_depth(root,depth):
parent_of = {root: None}
nodes_yielded = set()
vals_yielded = set()
stack = [(root,depth)]
while stack:
node,depth = stack.pop()
if depth == 0:
while node and node not in nodes_yielded:
if node.val not in vals_yielded:
vals_yielded.add(node.val)
yield node
nodes_yielded.add(node)
node = parent_of[node]
elif depth > 0:
for child in node.children:
parent_of[child] = node
stack.append((child,depth - 1))
if __name__ == "__main__":
"""
A*
|
-----
| |
B* C*
| |
| ---
| | |
D* E F*
/ | \ | \
G* H* I* J* K*
|
L
"""
Node = collections.namedtuple("Node","val children")
root = Node("A",(
Node("B",(
Node("D",(
Node("G",()),Node("H",Node("I",)),Node("C",(
Node("E",Node("F",(
Node("J",Node("K",(
Node("L",))
))
print([x.val for x in unique_nodes_on_paths_to_depth(root,3)])
# => ['K','F','C','A','J','I','D','B','H','G']
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。