【问题标题】:DFS implementation in HaskellHaskell 中的 DFS 实现
【发布时间】:2017-02-06 00:16:52
【问题描述】:

由于不知道如何在 Haskell 中编写 DFS,我已经摸索了几个小时。

我的图被实现为邻接列表,其中键(或图的节点名称)是列表索引:

0 -> 1
1 -> 0, 2
2 -> 1

As a Haskell list: [[1],[0,2],[1]]

到目前为止,这是我的 DFS 代码:

dfs graph visited node = helper graph visited (graph !! node) node
    where helper _ _ visited [] _ = visited
          helper graph visited (x:xs) currNode
            | elem x visited = helper graph visited xs currNode
            | otherwise = dfs graph (currNode:visited) x

我了解问题在于,一旦到达图表的一端,它就不会回溯并尝试另一个相邻节点。我一直在尝试修改守卫的其他部分以尝试修复它,但似乎无法提出可行的方法。我该怎么做才能解决这个问题?

【问题讨论】:

  • 这还能编译吗?在最坏的情况下,!! 的复杂度也是 O(n),所以你的 dfs 的复杂度会更大。
  • 如果这不是家庭作业,您可能想要使用功能图形库 (fgl)。大量模块看起来令人生畏,但实际上很容易使用。
  • 这对于答案来说太少了,但请看一下这篇论文:“Structuring Depth-First Search Algorithm in Haskell” www.researchgate.net/publication/2252048_Structuring_Depth-First_Search_Algorithms_in_Haskell/file/50463523c7a64b12d4.pdf – 这不是最容易掌握的,但是……嗯,应该表现得很好。稍后我会进行测试。

标签: haskell depth-first-search


【解决方案1】:

我仍然不太清楚您要做什么。我写了一些与你类似的东西,虽然它有同样的问题,!! 不是 O(1),但它仍然是 dfs。

mydfs graph visited [] = reverse visited
mydfs graph visited (x:xs) | elem x visited = mydfs graph visited xs
                           | otherwise = mydfs graph (x:visited) ((graph !! x) ++ xs)

dfs 回溯的想法是保留一个待访问列表,然后从中取出第一个条目并访问它,每当您发现未访问的条目时,将其相邻顶点推到待访问列表顶部。

您可以将数组或向量用于邻接列表以避免 O(n) 查找,但最好使用图形库来完成您正在尝试做的事情。

【讨论】:

    【解决方案2】:

    我能想到的最短的

    dfs current visited =
        foldl (\visited next -> if elem next visited then visited else dfs next visited)
               (visited ++ [current]) (graph !! current)
    

    与python比较:

    def dfs(v, visited):
        visited.append(v)
        for u in graph[v]:
            if u not in visited:
                visited = dfs(u, visited)
        return visited
    

    【讨论】:

      猜你喜欢
      • 2020-04-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-19
      • 2019-08-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多