@@ -32,28 +32,30 @@ function is_cyclic end
3232end
3333# see https://github.com/mauro3/SimpleTraits.jl/issues/47#issuecomment-327880153 for syntax
3434@traitfn function is_cyclic (g:: AG :: IsDirected ) where {T,AG<: AbstractGraph{T} }
35+ # 0 if not visited, 1 if visited, 2 if in the current dfs path, 3 if fully explored
3536 vcolor = zeros (UInt8, nv (g))
37+ vertex_stack = Vector {T} ()
3638 for v in vertices (g)
3739 vcolor[v] != 0 && continue
38- S = Vector {T} ([v] )
40+ push! (vertex_stack, v )
3941 vcolor[v] = 1
40- while ! isempty (S)
41- u = S[end ]
42- w = 0
43- for n in outneighbors (g, u)
44- if vcolor[n] == 1
45- return true
46- elseif vcolor[n] == 0
47- w = n
48- break
42+ while ! isempty (vertex_stack)
43+ u = vertex_stack[end ]
44+ if vcolor[u] == 1
45+ vcolor[u] = 2
46+ for n in outneighbors (g, u)
47+ # we hit a loop when reaching back a vertex of the main path
48+ if vcolor[n] == 2
49+ return true
50+ elseif vcolor[n] == 0
51+ # we store neighbors, but these are not yet on the path
52+ vcolor[n] = 1
53+ push! (vertex_stack, n)
54+ end
4955 end
50- end
51- if w != 0
52- vcolor[w] = 1
53- push! (S, w)
5456 else
55- vcolor[u] = 2
56- pop! (S )
57+ vcolor[u] = 3
58+ pop! (vertex_stack )
5759 end
5860 end
5961 end
@@ -85,34 +87,36 @@ graph `g` as a vector of vertices in topological order.
8587function topological_sort_by_dfs end
8688# see https://github.com/mauro3/SimpleTraits.jl/issues/47#issuecomment-327880153 for syntax
8789@traitfn function topological_sort_by_dfs (g:: AG :: IsDirected ) where {T,AG<: AbstractGraph{T} }
90+ # 0 if not visited, 1 if visited, 2 if in the current dfs path, 3 if fully explored
8891 vcolor = zeros (UInt8, nv (g))
8992 verts = Vector {T} ()
93+ vertex_stack = Vector {T} ()
9094 for v in vertices (g)
9195 vcolor[v] != 0 && continue
92- S = Vector {T} ([v] )
96+ push! (vertex_stack, v )
9397 vcolor[v] = 1
94- while ! isempty (S)
95- u = S[end ]
96- w = 0
97- for n in outneighbors (g, u)
98- if vcolor[n] == 1
99- error (" The input graph contains at least one loop." ) # TODO 0.7 should we use a different error?
100- elseif vcolor[n] == 0
101- w = n
102- break
98+ while ! isempty (vertex_stack)
99+ u = vertex_stack[end ]
100+ if vcolor[u] == 1
101+ vcolor[u] = 2
102+ for n in outneighbors (g, u)
103+ # we hit a loop when reaching back a vertex of the main path
104+ if vcolor[n] == 2
105+ error (" The input graph contains at least one loop." ) # TODO 0.7 should we use a different error?
106+ elseif vcolor[n] == 0
107+ # we store neighbors, but these are not yet on the path
108+ vcolor[n] = 1
109+ push! (vertex_stack, n)
110+ end
103111 end
104- end
105- if w != 0
106- vcolor[w] = 1
107- push! (S, w)
108112 else
109- vcolor[u] = 2
110- push! (verts, u )
111- pop! (S )
113+ vcolor[u] = 3
114+ pop! (vertex_stack )
115+ pushfirst! (verts, u )
112116 end
113117 end
114118 end
115- return reverse ( verts)
119+ return verts
116120end
117121
118122"""
0 commit comments