【问题标题】:DFS implementation for abstract graph in HaskellHaskell中抽象图的DFS实现
【发布时间】:2020-04-12 20:53:18
【问题描述】:

我正在尝试在 Haskell 中实现 DFS 算法,该算法将无法访问 Graph 内部和构造函数,但只能使用提供的函数来检索图中的所有图顶点和所有节点的邻居:

vertices :: Eq a => Graph a -> [a]
neighbors :: Eq a => Graph a -> a -> [a]

作为输入,该函数得到一个Graph a 和一个对象a

作为输出,我正在尝试提供一个连接组件Graph a,它将具有可从对象访问的所有顶点。

为了检索一个空图并添加我已经实现的函数的顶点

empty :: Graph a
addVertex :: Eq a => Graph a -> a -> Graph a

对于dfs,到目前为止,我已经实现了一个功能,它看起来更像是一个一般的想法,但还没有接近工作。 我觉得有点卡住了,所以非常感谢任何建议或提示

最后,我需要从输入中获取包含节点的图的连接组件。 (非强连接)

所以dfs 本身可能应该返回一个节点列表,然后可以使用neighbours 函数将其用于形成图形..?

到目前为止我有这个,但它仍然不能正常工作。

我剩下的唯一问题是将边缘保留在子图中

connectedComponent :: Eq a => Graph a -> a -> Graph a
connectedComponent g vrtx | vrtx `notElem`  vertices g = empty
                            --adds all the points to the created graph   
                          | otherwise = foldl (\graph x -> addVertex graph x) initialGraph points 
                                --gets all neighbors of the nodes retrieved in dfs
                                where 
                                    points = concatMap (neighbors g) (dfs g vrtx) 
                                    initialGraph = addVertex empty vrtx

-- Getting the Graph and a vertex to start from
dfs :: Eq a => Graph a -> a -> [a]
dfs graph node | graph == empty = []
               | [x|x<-(vertices graph),x==node] == [] = []
               | otherwise = dfs' (vertices graph) graph [node]

dfs' [] _ _ = []
dfs' _ _ [] = []
dfs' v graph (top:stack) | [x|x<-v,x==top] == [] = dfs' nextv graph stack
                     | otherwise = top : dfs' nextv graph (adjacent ++ stack)
                     where 
                        adjacent = neighbors graph top
                        --adjacent = [x | (x,y)<-e,y==top] ++ [x | (y,x)<-e,y==top]
                        nextv = [x|x<-v,x/=top]

【问题讨论】:

  • 我真的不明白为什么您的dfs 旨在返回Graph adfs 不应该返回路径或路径列表吗?
  • @WillemVanOnsem 就像我看到的那样,它应该返回一个子图,其中包含来自输​​入节点的所有可到达节点。我猜什么叫做连接组件。
  • 或者也许获取整个列表的所有邻居是有意义的。但是我不确定,如何创建一个函数connectedComponent :: Graph a -> Graph a,它将创建一个空图并在其中添加所有顶点和edes
  • 但是您正在实现的不是 DFS 本​​身,而是一种算法(可能使用 dfs 作为子路由):en.wikipedia.org/wiki/Strongly_connected_component#Algorithms
  • @WillemVanOnsem 谢谢,这实际上是有道理的,但是我需要检索一个连接的组件,而不是一个强连接的。

标签: algorithm haskell graph functional-programming depth-first-search


【解决方案1】:

这是我最后所做的,对我来说是正确的。

connectedComponent :: Eq a => Graph a -> a -> Graph a
connectedComponent g vrtx | vrtx `notElem`  vertices g = empty
                            --adds all the nodes and edges to the created graph   
                          | otherwise = foldl addEdge (foldl (\graph x -> addVertex graph x) initialGraph nodes) edges
                                --gets all neighbors of the nodes retrieved in dfs
                                where 
                                    nodes = concatMap (neighbors g) (dfs g vrtx) 
                                    -- init the graph with the start node
                                    initialGraph = addVertex empty vrtx
                                    edges = removeDub [(x,y) | x <- (vertices g), y <- (neighbors g x), x `elem` dfs g vrtx]

-- removes dublicates from the edges if (a,b) and (b,a) exist
removeDub ::Eq a => [(a,a)] -> [(a,a)]
removeDub [] = []
removeDub ((x,y):xs) | (y,x) `elem` xs = removeDub xs
                     | otherwise = (x,y) : removeDub xs


-- Getting the Graph and a vertex to start from
dfs :: Eq a => Graph a -> a -> [a]
dfs graph node | graph == empty = []
                 -- stop if this is the node
               | [x | x<-(vertices graph), x==node] == [] = []
               | otherwise = dfs' (vertices graph) graph [node]

-- help function for dfs
dfs' [] _ _ = []
dfs' _ _ [] = []
dfs' vs graph (top:stack) | [x | x <- vs, x==top] == [] = dfs' nextv graph stack
                        -- append the current one and go to the next node
                     | otherwise = top : dfs' nextv graph (adjacent ++ stack)
                     where
                        -- getting all neibourhs for currently viewed node 
                        adjacent = neighbors graph top
                        -- getting the next node
                        nextv = [x|x<-vs,x/=top]

【讨论】:

  • 要让 dfs 工作,您应该在某处(在代码中的 vs 中)跟踪访问过的节点。它应该开始为空并随着您访问节点而增长
猜你喜欢
  • 1970-01-01
  • 2014-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-30
  • 1970-01-01
  • 2020-02-19
相关资源
最近更新 更多