Mic*_*ael 5 scala traversal graph immutability
我知道的图遍历(DFS和BFS)实现使用一组可变的"访问"顶点.您将如何仅使用不可变数据结构来实现它们?
我看到了这个问题.现在我想知道是否还有其他解决方案
这是一种方法:
def traverse[A](graph : Map[A,Set[A]], toVisit : Seq[A], visited : Set[A]) : Seq[A] = {
if(toVisit.isEmpty) {
Seq.empty
} else {
val next = toVisit.head
val succ = (graph(next) -- visited -- toVisit).toSeq
// DFS :
// next +: traverse(graph, succ ++ toVisit.tail, visited + next)
// BFS :
next +: traverse(graph, toVisit.tail ++ succ, visited + next)
}
}
def traverseFrom[A](graph : Map[A,Set[A]], initial : A) =
traverse(graph, Seq(initial), Set.empty)
Run Code Online (Sandbox Code Playgroud)
诀窍就是传递要访问的节点列表(这对应于命令式算法中的堆栈或队列)以及访问状态集.
如果你担心每次递归调用都会增加调用堆栈,你可以使用额外的参数使其尾递归:
@annotation.tailrec
def traverseTR[A](graph : Map[A,Set[A]], toVisit : Seq[A], visited : Set[A], accumulator : Seq[A]) : Seq[A] = {
if(toVisit.isEmpty) {
accumulator
} else {
val next = toVisit.head
val succ = (graph(next) -- visited -- toVisit).toSeq
// DFS :
//traverseTR(graph, succ ++ toVisit.tail, visited + next, accumulator :+ next)
// BFS :
traverseTR(graph, toVisit.tail ++ succ, visited + next, accumulator :+ next)
}
}
def traverseFrom[A](graph : Map[A,Set[A]], initial : A) =
traverseTR(graph, Seq(initial), Set.empty, Seq.empty)
Run Code Online (Sandbox Code Playgroud)
这将为您提供一个高效的版本,就像您使用while循环编写它一样.
| 归档时间: |
|
| 查看次数: |
4448 次 |
| 最近记录: |