在Scala中修改节点树

时间:2017-11-03 16:49:36

标签: scala

enter image description here

我有一个节点树:

val root = Node("a", List(Node("w", Nil), Node("b", List(Node("c", List(Node("d", Nil))), Node("m", List(Node("n", Nil)))))))

和中间节点列表:

val ks = List("b", "m")

引导我到我必须添加节点的位置:

val child = Node("t", Nil)

导致:

val res = Node("a", List(Node("w", Nil), Node("b", List(Node("c", List(Node("d", Nil))), Node("m", List(Node("n", Nil), Node("t", Nil)))))))

Scala中的树被建模为:

sealed trait Tree[A]

case class Empty[A]() extends Tree[A]

case class Node[A](rootNode: A, subtree: List[Tree[A]]) extends Tree[A]

我尝试遍历树并添加节点,

@tailrec
def traverseAndAdd(root: Node[String], subNode: Node[String], child: Node[String], ls: List[String]): Node[String] = ls match {
  case Nil =>
    root
  case x :: Nil =>
    val k = subNode.subtree.filter(l => l.asInstanceOf[Node[String]].rootNode == x).head.asInstanceOf[Node[String]].subtree :+ child
    println(k)
    traverseAndAdd(root, subNode, child, Nil)
  case x :: xs =>
    traverseAndAdd(root, subNode.subtree.filter(l => l.asInstanceOf[Node[String]].rootNode == x).head.asInstanceOf[Node[String]], child, xs)
}

val root = Node("a", List(Node("w", Nil), Node("b", List(Node("c", List(Node("d", Nil))), Node("m", List(Node("n", Nil)))))))
val child = Node("t", Nil)
val ks = List("b", "m")

println("res: " + traverseAndAdd(root, root, child, ks))

我知道这里的列表是不可变的,甚至代码也没有尝试构建节点。我想要一个关于如何在Scala中实现这样的事情的建议。请帮忙。

另外,我已经尝试过这个问题,这个问题是使用正常(非尾部)递归的子问题,但我最终得到的数据堆栈流量是巨大的。所以想到这种方法!

1 个答案:

答案 0 :(得分:1)

我注意到您的代码中存在一些缺点。

  • class Empty已定义但从未使用过。
  • val k已填充但从未使用过。
  • 您的数据结构不需要唯一性,因此不保证给定的节点路径是唯一的。

这是我能够构建的。它不是尾递归,也不是解决唯一性问题,但似乎有效。

case class Node[A](elem: A, subNodes: List[Node[A]])

def addNode[T](node: Node[T], path: List[T]): Node[T] = {
  if (path.isEmpty)
    node
  else if (path.head == node.elem)
    addNode(node, path.tail)
  else if (node.subNodes.map(_.elem).contains(path.head))
    Node(node.elem, node.subNodes.map{n =>
      if (n.elem == path.head) addNode(n,path.tail)
      else n
    })
  else
    Node(node.elem
        ,node.subNodes :+ addNode(Node(path.head, List[Node[T]]()), path.tail))
}

val root = Node("a", List(Node("w", Nil)
                         ,Node("b", List(Node("c", List(Node("d", Nil)))
                                        ,Node("m", List(Node("n", Nil)))))))
addNode(root,List("a","b","m","n","t"))