给定一个边列表(parent< - > child),如何在递归数据结构中组装隐含的有向根树(任何子节点为1父节点,任何父节点无限制子节点){{1没有冒简单递归带来的堆栈溢出错误的风险?
Scala的奖金:
class Node(name: String, children: Array[Node])
答案 0 :(得分:1)
我几乎不了解Scala,但这是一个非常与语言无关的问题。
首先,除非每个节点只有一个孩子,否则您的parentToChild
数据结构没有意义。不太可能。您可能需要MultiMap
。
该算法非常简单:首先通过parentToChild
多重映射只是为了构建一个新映射Name -> Node
,其中所有节点中的子节点列表都是空的。然后再次通过parentToChild
并使用新地图添加子指针。
我无法理解为什么你会认为递归会起作用。这是一个简单的迭代。
这里的伪代码:
set nameToNode = \empty
for each entry (parentName, childName) in parentToChild
nameToNode.addIfNotPresent(parentName, new Node(parentName))
nameToNode.addIfNotPresent(childName, new Node(childName))
for each entry (parentName, childName) in parentToChild
set parent = nameToNode.get(parentName)
set child = nameToNode.get(childName)
parent.chilren.add(child)
如果您还不知道根节点,请添加以下内容:
set roots = \empty
set nodeToHasInwardEdge = \empty
for each entry (name, node) in nameToNode // name is ignored
for each child in node.children
nodeToHasInwardEdge.put(child, true)
for each entry (name, node) in nameToNode // name is ignored
if nodeToHasInwardEdge.get(node) == null
roots.add(node)
实际上,您可以将上面的第一个循环与前一个代码段中的第二个循环合并,因此只需要3遍就可以添加所有边并查找所有根。即使您认为您知道根,但最好将其用作检查。只需验证一个根目录。类似地,如果输入应该表示树,则可以使用整数计数而不是上面的布尔值,并验证每个非根节点只有一个入边。