Haskell中的DFS实现

时间:2012-10-05 03:20:47

标签: haskell depth-first-search

我一直在墙上撞了几个小时,因为我无法弄清楚如何在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

我知道问题是它一旦到达图的一端就不会回溯并尝试另一个相邻节点。我一直在尝试修改防护部分的其他部分,试图修复它,但似乎无法想出一些有效的东西。我该怎么做才能解决这个问题?

2 个答案:

答案 0 :(得分:2)

你要做的事情对我来说仍然不是很清楚。虽然它有!!不是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)查找,但最好将图库用于您要执行的操作。

答案 1 :(得分:0)

最短的我可以想出

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