algorithm - 是否可以在 Haskell 中实现线性时间 BFS?

标签 algorithm haskell functional-programming

我有一个有向图 G 作为邻接列表的列表:

newtype Graph Int = Graph [(Int, [Int])]

G有n个顶点和m条边。我正在尝试在 Haskell 中实现 BFS 算法,该算法在 O(m) 时间内运行(可能摊销),但我能够想出的最佳解决方案在 O(m * log n) 中运行并使用 中的数据结构Data.Map模块。

我对线性解决方案的想法如下:使用 Data.Sequence 中的结构作为高效的 FIFO 队列,并按照命令式 BFS 的方式执行所有操作,但我被困在必须标记的位置访问过的节点。

我的问题是:是否可以在运行时间复杂度为 O(m) 的 Haskell(或任何其他纯函数式语言)中实现 BFS?如果不是,您可以使用什么论据来证明这种说法?

最佳答案

我假设你的问题是你不能实现一个好的队列。

看看 Data.Sequence - 它应该适用于双端队列,因为对序列末尾的操作非常快。向任一端添加一个元素是 O(1),从任一端删除一个元素是 O(1)

一旦拥有队列,它的性能应该与 DFS 一样好。

您可以使用 Vector Int [Int] 而不是 Map Int [Int](如果您的顶点是 1n)

要将节点标记为已选中,您可以使用 IntSet

这应该得到 O(V + E)

bfs :: V.Vector [Int] -> Int -> [Int]
bfs graph start = go IS.empty graph $ S.singleton start

go :: IS.IntSet Int -> V.Vector [Int] -> S.Sequence Int -> [Int]
go seen graph queue = 
  case S.viewL queue of
    S.EmptyL -> []
    vertex S.:< rest = vertex:(go seen' graph queue')
      where neighbors = filter (not . IS.member seen) (graph V.! vertex)
            seen' = S.insert vertex seen
            queue' = queue S.>< S.fromList neighbors

请注意,我们构建此列表的方式完全是惰性的!因此,如果您只需要 BFS 的前半部分,则不会计算其余部分。

关于algorithm - 是否可以在 Haskell 中实现线性时间 BFS?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26745679/

相关文章:

algorithm - 从中序和后序遍历构造二叉树

haskell - Haskell中的外部函数?

Haskell 使用保护方程创建类型

haskell - 使用 Haskell 给定一些数据生成 SBV 公式的简单方法是什么?

haskell - Haskell 中的 GHCI 与 Prelude 命令提示符

functional-programming - java 8中构造函数引用的用途是什么

haskell - 接受一个字符数组并返回一个连接字符串的函数。 haskell

java - 将无关紧要展开为二进制数的递归方法

algorithm - matlab中时滞神经网络的反向传播算法

algorithm - Theta星算法和Phi星算法的主要区别是什么?