File: graph-dfs.sml

package info (click to toggle)
mlton 20210117%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 58,464 kB
  • sloc: ansic: 27,682; sh: 4,455; asm: 3,569; lisp: 2,879; makefile: 2,347; perl: 1,169; python: 191; pascal: 68; javascript: 7
file content (87 lines) | stat: -rw-r--r-- 2,791 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
(*
 * Some simple functions for performing depth first search
 *
 * -- Allen
 *)
structure GraphDFS : GRAPH_DEPTH_FIRST_SEARCH = 
struct

   structure G = Graph
   structure A = Array
   structure S = BitSet

   (*
    * Depth first search
    *)
   fun dfs (G.GRAPH G) f g roots =
   let val visited = S.create(#capacity G ())
       fun traverse n =
           if S.markAndTest(visited,n) then ()
           else (f n; app traverse_edge (#out_edges G n))
       and traverse_edge (e as (_,n,_)) =
           if S.markAndTest(visited,n) then ()
           else (g e; f n; app traverse_edge (#out_edges G n))
   in  app traverse roots end

   (*
    * Depth first search fold
    *)
   fun dfsfold (G.GRAPH G) f g roots (x,y) =
   let val visited = S.create(#capacity G ())
       fun traverse(n,x,y) =
           if S.markAndTest(visited,n) then (x,y)
           else traverse_edges(#out_edges G n,f(n,x),y)
       and traverse_edges ([],x,y) = (x,y)
         | traverse_edges ((e as (_,n,_))::es,x,y) =
           if S.markAndTest(visited,n) then traverse_edges(es,x,y)
           else let val y = g(e,y)
                    val x = f(n,x)
                    val (x,y) = traverse_edges(#out_edges G n,x,y)
                in  traverse_edges(es,x,y) end
       and traverseAll([],x,y) = (x,y)
         | traverseAll(n::ns,x,y) = 
            let val (x,y) = traverse(n,x,y)
            in  traverseAll(ns,x,y) end
   in  traverseAll(roots,x,y) end


   fun dfsnum (G.GRAPH G) roots =
   let val N       = #capacity G ()
       val dfsnum  = A.array(N,~1)
       val compnum = A.array(N,~1)
       fun traverse([],d,c) = c
         | traverse(n::ns,d,c) =
           if A.sub(dfsnum,n) >= 0 then traverse(ns,d,c)
           else  let val _ = A.update(dfsnum,n,d); 
                     val c = traverse(#succ G n,d+1,c)
                 in  A.update(compnum,n,c);  
                     traverse(ns,d,c+1)
                 end
   in  traverse(roots,0,0); {dfsnum=dfsnum,compnum=compnum} end

   fun preorder_numbering (G.GRAPH G) root =
   let val N = #capacity G ()
       val P = A.array(N,~1)
       fun f(i,n) = 
           if A.sub(P,i) = ~1 then
              let fun g([],n) = n 
                    | g((_,j,_)::es,n) = g(es,f(j,n))
              in  A.update(P,i,n); g(#out_edges G i,n+1) end
           else n
   in  f(root,0); P end

   fun postorder_numbering (G.GRAPH G) root =
   let val N = #capacity G ()
       val P = A.array(N,~2)
       fun f (i,n) = 
           if A.sub(P,i) = ~2 then
              let fun g([],n) = n
                    | g((_,j,_)::es,n) = g(es,f(j,n))
                  val _ = A.update(P,i,~1)
                  val n =  g(#out_edges G i,n) 
              in  A.update(P,i,n); n+1
              end
           else n
   in  f(root,0); P end
end