我正在尝试使用Scala实现一个功能性的广度优先搜索算法,用于计算无权图中给定节点与所有其他节点之间的距离。我已经使用了State Monad,并将其签名定义为:
case class State[S,A](run:S => (A,S))
其它函数,例如map、flatMap、sequence、modify等等与标准的State Monad内部所包含的类似。
以下是代码:
case class Node(label: Int)
case class BfsState(q: Queue[Node], nodesList: List[Node], discovered: Set[Node], distanceFromSrc: Map[Node, Int]) {
val isTerminated = q.isEmpty
}
case class Graph(adjList: Map[Node, List[Node]]) {
def bfs(src: Node): (List[Node], Map[Node, Int]) = {
val initialBfsState = BfsState(Queue(src), List(src), Set(src), Map(src -> 0))
val output = bfsComp(initialBfsState)
(output.nodesList,output.distanceFromSrc)
}
@tailrec
private def bfsComp(currState:BfsState): BfsState = {
if (currState.isTerminated) currState
else bfsComp(searchNode.run(currState)._2)
}
private def searchNode: State[BfsState, Unit] = for {
node <- State[BfsState, Node](s => {
val (n, newQ) = s.q.dequeue
(n, s.copy(q = newQ))
})
s <- get
_ <- sequence(adjList(node).filter(!s.discovered(_)).map(n => {
modify[BfsState](s => {
s.copy(s.q.enqueue(n), n :: s.nodesList, s.discovered + n, s.distanceFromSrc + (n -> (s.distanceFromSrc(node) + 1)))
})
}))
} yield ()
}
请问:
searchNode
函数中出队列时状态转移应该是BfsState
的成员吗?- 如何使这段代码更高效、简洁和易读?
State
并不是很有用,因为它并没有被广泛使用。在这种情况下,State
只有一个真实的值,而使用State
所增加的复杂性远大于其提供的好处。如果你正在做一些更复杂的事情,State
会更有用,但在这里却不是这样。 - HTNW