我正在写一个简单的广度优先搜索算法Scala,我觉得它应该非常有效。但是,当我运行这一程序时,我遇到了一些相对较小的问题,导致内存不足。
values.price ? `You'll pay ${values.price}` : null
我相信可变队列上的入队和出队方法是固定时间的,并且每种方法都可以有效地实现。方法是目标,我所知道的后继者会尽可能地高效。我不明白我怎么会这么快用尽内存。我缺少此代码中的任何低效率吗?
答案 0 :(得分:1)
我认为c0der的注释很明确:您可能陷入无限循环,重新检查您已经访问过的节点。请考虑以下更改:
def search(start: State): Option[State] = {
var visited: Set[State] = Set() // change #1
val queue: mutable.Queue[State] = mutable.Queue[State]()
queue.enqueue( start )
while( queue.nonEmpty ){
val node = queue.dequeue()
if (!visited.contains(node)) { // change #2
visited += node // change #3
if( self.isGoal(node) )
return Some(node)
self.successors(node).foreach( queue.enqueue )
}
}
None
}
visited
,以跟踪您去过的节点。visited
集中,以便以后不再进行检查。希望有帮助:D
答案 1 :(得分:1)
您那里有一些Java而不是Scala代码。对于Scala var,虽然while根本不应该使用。这是我的建议,您如何解决这个问题。
class State(val neighbours: List[State]) // I am not sure how your State class looks like, but it could look something like this
val goal = new State(List())
def breathFirst(start: State): Option[State] = {
@scala.annotation.tailrec
def recursiveFunction(visited: List[State], toVisit: List[State]): Option[State] = { // So we will create recursive function with visited nodes and nodes that we should visit
if (toVisit.isEmpty) return None // If toVisit is empty that means that there is no path from start to goal, return none
else {
val visiting = toVisit.head // Else we should take first node from toVisit
val visitingNeighbours = visiting.neighbours // Take all neighbours from node that we are visiting
val visitingNeighboursNotYetVisited = visitingNeighbours.filter(x => !visited.contains(x)) //Filter all neighbours that are not visited
if (visitingNeighboursNotYetVisited.contains(goal)) { //if we found goal, return it
return Some(goal)
} else {
return recursiveFunction(visited :+ visiting, toVisit.tail ++ visitingNeighboursNotYetVisited) // Otherwise add node that we visited in this iteration to list of visited nodes that does not have visited node - it was head so we take toVisit.tail
// and also we will take all neighbours that are not visited and add them to toVisit list for next iteration
}
}
}
if (start == goal) { // If goal is start, return start
Some(start)
} else { // else call our recursive function with empty visited list and with toVisit list that has start node
recursiveFunction(List(), List(start))
}
}
注意:您可以更改:
val visitingNeighboursNotYetVisited = visitingNeighbours.filter(x => !visited.contains(x)) //Filter all neighbours that are not visited
使用
val visitingNeighboursNotYetVisited = visitingNeighbours
并检查是否会耗尽内存,并且可能不会告诉您为什么应该使用tailrec。