If you're looking for topological sort
, you can also do this, given an adjacency list (or a list of edges (u,v)
which you can preprocess in O(E)
time):
list top_sort( graph in adjacency list )
parent = new list
queue = new queue
for each u in nodes
parent(u) = number of parents
if ( parent(u) is 0 ) // nothing points to node i
queue.enqueue( u )
while ( queue is not empty )
u = queue.pop
add u to visited
for each edge ( u, v )
decrement parent(v) // children all have one less parent
if ( parent(v) is 0 )
queue.enqueue( v )
Given an adjacency list
(or a list of edges (u,v)
), this is O( V + E )
, since each edge is touched twice - once to increment, once to decrement, in O(1)
time each. With a normal queue, each vertice will also be processed by the queue at most twice - which can be done also in O(1)
with a standard queue.
Note that this differs from the DFS (at least a straight-up implementation) in that it handles forests.
Another interesting note is that if you substitute queue
with a priority_queue
imposing some sort of structure/ordering, you can actually return the results sorted in some order.
For example, for a canonical class dependency graph (you can only take class X if you took class Y):
100:
101: 100
200: 100 101
201:
202: 201
you would probably get, as a result:
100, 201, 101, 202, 200
but if you change it so that you always want to take lower numbered classes first, you can easily change it to return:
100, 101, 200, 201, 202