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 更高效
运行代码
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))))