0

I want to create a function in SML that does a BFS traversal of an undirected graph e.x Graph = [|[2],[3,4],[1,2],[2]|].

fun bfs (g: graph) (n: vertex): vertex list = 
let
  fun helper (todo: vertex list) (visited: vertex list) =
    case todo of
      [] => []
    | h::t => if (List.exists (fn x => x = h) visited)
              then helper t visited
              else
                let
                  val adj = case List.find (fn (n, _) => n = h) g of
                            NONE => raise Fail "incomplete adjacency list"
                          | SOME (_, adj) => adj
                in
                  h :: (helper (t @ adj) (h::visited))
                end
in
  helper [n] []
end

I found this example but i dont know how to change it to correspond to my type of graph

  • Which parts of it, and BFS in general, don't you understand? (Modifying "found code" so it fits your own situation rarely works. The only thing that works reliably is learning how and why it works, and then writing a new solution for yourself.) – molbdnilo Apr 28 '20 at 18:16
  • I know how BFS works, but because I am new to sml I cant really think of a way to implement it. If you have some more in depth material, it might help but i cant find any – CuriousPeet Apr 28 '20 at 18:23
  • In this code. `todo` is the queue of nodes to visit next, `visited` is the list of already-visited nodes, and the graph is a list of adjacency lists. It's not clear how your `[|[2],[3,4],[1,2],[2]|]` represents a graph. – molbdnilo Apr 29 '20 at 10:07
  • In the code above the graph is represented this way `g = [(1, [2,]), (2, [3,4]), (3, [1,2]), (4, [2)]`. My graph just doesnt use tuples because I use an array. – CuriousPeet Apr 29 '20 at 10:35

1 Answers1

0

I would start by factoring out the part of that code which depends on the representation of the graph:

(* returns list of all vertices that are adjacent to h *)
fun getNeighbors g h =
  case List.find (fn (n, _) => n = h) g of
    NONE => raise Fail "incomplete adjacency list"
  | SOME (_, adj) => adj


fun bfs (g: graph) (n: vertex): vertex list = 
let
  fun helper (todo: vertex list) (visited: vertex list) =
    case todo of
      [] => []
    | h::t => if (List.exists (fn x => x = h) visited)
              then helper t visited
              else
                let
                  val adj = getNeighbors g h
                in
                  h :: (helper (t @ adj) (h::visited))
                end
in
  helper [n] []
end

Now you just need to implement a new getNeighbors function for your graph representation. It should return a list of adjacent vertices.

Sam Westrick
  • 1,248
  • 1
  • 7
  • 9