Если вы ищете topological sort
, вы также можете сделать это, учитывая список смежностей (или список ребер (u,v)
, которые вы можете предварительно обработать за O(E)
время):
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 )
Учитывая adjacency list
(или список ребер (u,v)
), это O( V + E )
, поскольку каждое ребро касается дважды - один раз для увеличения, один для уменьшения, в O(1)
каждый раз. При обычной очереди каждая вершина также будет обрабатываться очередью не более двух раз - что можно сделать также в O(1)
со стандартной очередью.
Обратите внимание, что это отличается от DFS (по крайней мере, простой реализации) тем, что он обрабатывает леса.
Еще одно интересное замечание: если вы замените queue
на priority_queue
, навязывая какую-то структуру / упорядочение, вы на самом деле можете вернуть результаты, отсортированные в некотором порядке.
Например, для канонического графа зависимостей классов (вы можете взять класс X, только если вы взяли класс Y):
100:
101: 100
200: 100 101
201:
202: 201
вы, вероятно, получите, в результате:
100, 201, 101, 202, 200
но если вы измените его так, что вы всегда хотите сначала брать классы с меньшими номерами, вы можете легко изменить его так, чтобы он возвращал:
100, 101, 200, 201, 202