【问题标题】:How to optimize building a tree from a list of the node paths?如何优化从节点路径列表构建树?
【发布时间】:2019-03-25 16:57:22
【问题描述】:

假设我正在编写一个函数fromPaths(paths: List[String]): Node 来从这样的几个节点路径构建一棵树:

case class Node(value: String, children: List[Node])
val paths = List("a/b/x", "a/b/y", "a/c", "a/c/d")
fromPaths(paths) // Node("a", List(Node("b", List(Node("x"), Node("y"))), Node("c", List(Node("d")))))

我可以编写一个函数addNode(root: Node, path: String): Node,然后在列表中添加fold。但是它看起来不是最理想的,因为我们为paths 中的每个“路径”遍历了从rootnode 的树。

您将如何优化 fromPaths 的遍历节点总数?

【问题讨论】:

  • 您到底尝试了什么,输入"a", "a/b/c" 应该发生什么?您生成的树是否应该与 "a", "a/b", "a/b/c" 相同(内部节点上没有标记?)?
  • 对于"a", "a/b/c",结果应该是Node("a", List(Node("b", List(Node("c"))))
  • 我尝试了一些paths前缀分组...
  • List(Node("b"), List(Node("c"))) 甚至没有任何有意义的类型检查?..所有Node 构造函数都有错误的arity...再次:["a/b"] 和的结果之间是否应该没有区别? ["a", "a/b"]?
  • 哦,对不起。我的意思是Node("a", List(Node("b", List(Node("c")))))

标签: algorithm scala optimization tree


【解决方案1】:

明显的递归似乎工作得很好,至少在你的例子中:

case class Node[A](a: A, children: List[Node[A]])
def trieForest[A](lists: List[List[A]]): List[Node[A]] = {
  lists.filter(_.nonEmpty).groupBy(_.head).map { 
    case (k, vs) =>
    Node(k, trieForest(vs.map(_.tail)))
  }.toList
}

def fromPaths(paths: List[String]): Node[String] = {
  // assumes that there is only one tree in the 
  // top-level forest.
  trieForest(paths.map(_.split("/").toList)).head
}

println(fromPaths(List("a/b/x", "a/b/y", "a/c", "a/c/d")))

打印(直到压痕):

Node(a, List(
  Node(b,List(
    Node(y,List()), 
    Node(x,List())
  )),
  Node(c,List(
    Node(d,List())
  ))
))

它不能渐近地运行得更快,因为您必须至少查看输入的每个部分一次。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-11-07
    • 2020-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-16
    相关资源
    最近更新 更多