我使用Map:
获得了树状结构val m = Map[Int, (Set[Int], Set[Int])]()
其中node id由id表示,每个set分别是节点和子节点的父节点。我试图以递归方式计算节点上方和下方的层数。例如,我得到的树就像(0 - 1 - 2 - (3,4)),并且我希望某些函数能够将结果作为集合列表返回给每个集合,其中每个集合都是树的层。我有以下方法收集所有父母
def p(n:Set[Int]):Set[Int] = if(n.isEmpty) Set.empty else n ++ m(n.head)._1 ++ p(n.tail)
但是我希望按树的相应级别对其进行分组,以便通过调用大小来获得所需的结果。
UPD:
m = Map(0 -> (Set(), Set(1), 1 -> (Set(0), Set(2,3)), 2 -> (Set(1), Set(4,5), 3 -> (Set(2), Set(6,7) ....)
这就是我的地图m在填满树节点后的样子,我想从中获得另一张地图,看起来像:
Map(0 -> (List(Set()), List(Set(1), Set(2,3), Set(4,5,6,7)), 1 -> (List(Set(), Set(0)), List(Set(2,3), Set(4,5,6,7)) ... and so on)
那就是我希望它按每个级别分组,其中所有父级图层都在集合中,所有子图层都在集合中。
以下是简化示例:
val m = Map(2 -> (Set(1),Set(3, 4)), 4 -> (Set(2),Set()), 1 -> (Set(0),Set(2)), 3 -> (Set(2),Set()), 0 -> (Set(),Set(1)))
这是以下结构的树0 - 1 - 2 - 3,4
所以这里0是它有一个孩子的根,它有一个孩子2,它有2个孩子3和4.在更复杂的情况下,节点可以有多个父母,但所有这些都是唯一的,这就是我选择的原因设置,虽然它可能是其他任何东西,但是使用set我可以轻松地向上收集所有父节点并向下收集所有子节点,我唯一想让它们按照所驻留的级别进行分组。在这种情况下,节点3应该将List(Set(2),Set(1),Set(0),Set())作为其父项。
答案 0 :(得分:1)
BFS类型的遍历
进行BFS
种遍历并继续将nodes
添加到map
以更正级别
BFS
保留一个队列(在此代码中使用List
作为队列)并逐级访问树/图。这就是我们所需要的。
需要注意的一点是如何keep track of end of the level
。我使用EndOfLevel
当您发现EndOfLevel
时,如果队列中还有元素,则添加另一个EndOfLevel
,如果不知道我们已完成并返回结果。
sealed trait Node
case class ANode(value: Int) extends Node
case object EndOfLevel extends Node
def bfs(root: Node, map: Map[Node, (Set[Node], Set[Node])]): List[(Int, Set[Node])] = {
@tailrec
def helper(queue: List[Node], level: Int, result: Map[Int, Set[Node]]): List[(Int, Set[Node])] = {
if (queue.nonEmpty) {
queue.head match {
case anode@ANode(_) =>
val newQueue = queue.tail ++ getNodes(anode, map)
val newResult: Map[Int, Set[Node]] =
if (result contains level) {
result + (level -> (Set(anode) ++ result(level)))
} else {
result + (level -> Set(anode))
}
helper(newQueue, level, newResult)
case EndOfLevel =>
if (queue.tail.nonEmpty) helper(queue.tail ++ List(EndOfLevel), level + 1, result) else result
}
} else result
}
helper(List(root) ++ List(EndOfLevel), 0, Map(0 -> Set.empty[Node])).toList
}
def getNodes(node: Node, map: Map[Node, (Set[Node], Set[Node])]): Set[Node] = {
val (left, right) = map.getOrElse(node, (Set.empty[Node], Set.empty[Node]))
left ++ right
}
请注意,您可以使用Vector
代替List
使代码更优化。Vector
append
的效果比List
<更高/ em>的
正在运行代码
sealed trait Node
case class ANode(value: Int) extends Node
case object EndOfLevel extends Node
object Main {
def bfs(root: Node, map: Map[Node, (Set[Node], Set[Node])]): List[(Int, Set[Node])] = {
def helper(queue: List[Node], level: Int, result: Map[Int, Set[Node]]): Map[Int, Set[Node]] = {
if (queue.nonEmpty) {
queue.head match {
case anode@ANode(_) =>
val newQueue = queue.tail ++ getNodes(anode, map)
val newResult: Map[Int, Set[Node]] =
if (result contains level) {
result + (level -> (Set(anode) ++ result(level)))
} else {
result + (level -> Set(anode))
}
helper(newQueue, level, newResult)
case EndOfLevel =>
if (queue.tail.nonEmpty) helper(queue.tail ++ List(EndOfLevel), level + 1, result) else result
}
} else result
}
helper(List(root) ++ List(EndOfLevel), 0, Map(0 -> Set.empty[Node])).toList
}
def main(args: Array[String]): Unit = {
val map: Map[Node, (Set[Node], Set[Node])] = Map(
ANode(1) -> (Set[Node](ANode(2)) -> Set[Node](ANode(3))),
ANode(2) -> (Set[Node](ANode(4)) -> Set[Node](ANode(5))),
ANode(3) -> (Set[Node](ANode(6)) -> Set[Node](ANode(7)))
)
println(bfs(ANode(1), map))
}
def getNodes(node: Node, map: Map[Node, (Set[Node], Set[Node])]): Set[Node] = {
val (left, right) = map.getOrElse(node, (Set.empty[Node], Set.empty[Node]))
left ++ right
}
}
<强>输出强>
List((0,Set(ANode(1))), (1,Set(ANode(3), ANode(2))), (2,Set(ANode(7), ANode(6), ANode(5), ANode(4))))