module Data.Graph.Traversal
( bfsVertices
, dfsVertices
) where
import Data.List (foldl')
import Data.Hashable
import qualified Data.Set as S
import Data.Graph.Types
bfsVertices :: (Graph g, Hashable v, Eq v, Ord v) => g v e -> v -> [v]
bfsVertices g fromV = go [fromV] S.empty []
where
go [] _ popped = popped
go (v:vs) visited popped =
let reachables = nonVisitedReachables g visited v
in go
(vs ++ reachables)
(setInsertMany visited $ v : reachables)
(popped ++ [v])
dfsVertices :: (Graph g, Hashable v, Eq v, Ord v) => g v e -> v -> [v]
dfsVertices g fromV = go [fromV] S.empty []
where
go [] _ popped = popped
go (v:vs) visited popped =
let reachables = nonVisitedReachables g visited v
in go
(reachables ++ vs)
(setInsertMany visited $ v : reachables)
(popped ++ [v])
nonVisitedReachables :: (Graph g, Hashable v, Eq v, Ord v)
=> g v e
-> S.Set v
-> v
-> [v]
nonVisitedReachables g visited v = filter
(\v' -> not $ S.member v' visited)
(reachableAdjacentVertices g v)
setInsertMany :: Ord a => S.Set a -> [a] -> S.Set a
setInsertMany = foldl' (flip S.insert)