如何在没有堆栈溢出的情况下将List转换为Tree

时间:2016-09-15 14:54:54

标签: scala

我有列表[(nodeID,parentID)] - >的问题树结构

val tree: List[(Int, Int)] = List((1,0),(2,0),(3,0),(4,1),(5,4),(6,2),(7,6))

我的树案例类

case class Tree(value: Int, subTree: List[Tree])

我的代码

def DFS(tree: List[(Int, Int)], id: Int): List[Tree] = {
     if(tree.isEmpty) Nil
     else List(Tree(id, tree.filter(x => x._2 == id).flatMap(x => DFS(tree, x._1))))}

结果

List(Tree(0,List(Tree(1,List(Tree(4,List(Tree(5,List()))))), Tree(2,List(Tree(6,List(Tree(7,List()))))), Tree(3,List()))))

我发现列表中的大数据堆栈溢出

所以我想把它改成尾递归,贴图或折叠

3 个答案:

答案 0 :(得分:1)

tree DFS参数永远不会变小。因此,您永远不会遇到基本情况。

请拨打电话:DFS(tree.tail, x._1)

答案 1 :(得分:1)

从性能的角度来看,还有很多需要改进的地方,但似乎有效:

val tree: List[(Int, Int)] = List((1,0),(2,0),(3,0),(4,1),(5,4),(6,2),(7,6))
case class Tree(value: Int, subTree: List[Tree])

// Sort in reverse BFS order
@annotation.tailrec
def BFS(tree: List[(Int, Int)], ids: List[(Int, Int)], acc: List[(Int, Int)]): List[(Int, Int)] = {
  ids match {
    case Nil => acc
    case head::tail =>
      BFS(tree, tail ++ tree.filter(_._2 == head._1), head::acc) 
  }
}

// acc: List of (parent, Tree)
@annotation.tailrec
def fold(bfs: List[(Int, Int)], acc: List[(Int, Tree)]): List[(Int, Tree)] = {
  bfs match {
    case Nil => acc
    case head::tail =>
      val (l, r) = acc.partition(_._1 == head._1)
      fold(tail, (head._2, Tree(head._1, l.map(_._2))) :: r)
  }
}

fold(BFS(tree, List((0, 0)), Nil), Nil).map(_._2)

答案 2 :(得分:0)

尽管使尾部递归可能需要一些时间,但您可以按照以下方式进行操作。

val tree: List[(Int, Int)] = List((1,0),(2,0),(3,0),(4,1),(5,4),(6,2),(7,6))

def DFS(tree: List[(Int, Int)], id: Int): List[Tree] = tree match {
  case Nil => List[Tree]()
  case list =>
    val (children, others) => list.partition(x => x._2 == id)
    List(Tree(id, children.flatMap(x => DFS(others, x._1))))
}