我目前正在关注Timraoughgarden在Coursera上的“算法”专业知识,以及模块2,第1周的作业涉及计算图中强连接组件的大小。我可以为较小的图形计算它们,但是问题的问题有大约500万条边。我的解决方案运行得相当快,但是花了数小时试图使其在整套设备上运行,而我却花了一点时间在AWS超级计算机上花了一些时间,有人能帮助我找到解决此堆栈溢出错误的方法吗? >
我已经取消了预处理步骤,在该步骤中,将数组放入邻接列表中,并以正确的顺序将其传递到master_dfs中。
import scala.io.Source
object Main extends App {
def dfs(adjList: Map[Int, List[Int]], currentNode: Int,
foundNodes: Set[Int], finishingTime: List[Int]): (Set[Int],
List[Int]) = {
val foundsWithCurrent: Set[Int] = foundNodes + currentNode
val edges: List[Int] = adjList(currentNode)
val crossOver: List[Int] = edges.filterNot(node =>
foundNodes.contains(node))
if (crossOver.nonEmpty) {
val (nextStepFinds, nextStepFinishers) =
dfs(adjList, crossOver.head, foundsWithCurrent, finishingTime)
dfs(adjList, currentNode,
nextStepFinds, nextStepFinishers)
}
else (foundsWithCurrent, currentNode :: finishingTime)
}
def master_dfs(orderOfExecution: List[Int], adjList: Map[Int,
List[Int]], foundNodes: Set[Int], finishedList: List[Int], sccs:
List[List[Int]]): (Set[Int], List[Int], List[List[Int]]) = {
val (foundThisPass, finishers) = dfs(adjList = adjList,
currentNode = orderOfExecution.head, foundNodes = foundNodes,
finishingTime = finishedList)
val scc: List[Int] = finishers.filterNot(node =>
finishedList.contains(node))
val leftToExecute = orderOfExecution.filterNot(node =>
foundThisPass.contains(node))
if (leftToExecute.isEmpty) {
(foundThisPass, finishers, scc :: sccs)
}
else {
master_dfs(orderOfExecution = leftToExecute, adjList = adjList,
foundNodes = foundThisPass, finishedList = finishers, sccs =
scc :: sccs)
}
}
答案 0 :(得分:0)
由于大多数语言中的堆栈空间都是有限的,因此您始终需要考虑递归实现算法时将要使用多少堆栈空间。
当您知道搜索深度(即到任何节点的最大路径长度)受到限制时,在树或DAG上以递归方式实施DFS是可以的。
但是,在一般的有向图或无向图上,图中的最长路径可能包含图中大部分的顶点,并且递归DFS实现的调用深度可以与该路径一样长。这可能会导致大量输入的堆栈溢出。
当您不确定所有输入图的深度是否足以确保安全时,您应该使用堆栈对象迭代地实现DFS,而不是使用调用堆栈来递归实现。
由于堆栈对象与调用堆栈没有相同的限制,因此迭代实现可以处理更大的输入。