Menu
Coddy logo textTech

Ordenação Topológica

Última atualização

Uma ordenação topológica de um grafo acíclico dirigido (DAG) é uma ordenação linear de seus nós tal que, para cada aresta u → v, u vem antes de v. Ela responde perguntas como «em que ordem posso executar estas tarefas para que cada pré-requisito termine primeiro?». Pressione reproduzir acima para ver o algoritmo de Kahn retirar os nós em uma ordem válida.

O algoritmo de Kahn pega repetidamente um nó sem arestas de entrada restantes (grau de entrada 0), acrescenta-o à ordem e remove suas arestas de saída, o que pode liberar novos nós com grau de entrada 0. Ele só funciona em um DAG: se existir um ciclo, alguns nós nunca chegam a grau de entrada 0 e não há ordem válida. Executa em tempo O(V + E).

Complexidade de tempo e espaço

MedidaComplexidadeNotas
TempoO(V + E)Cada nó é emitido uma vez, cada aresta é removida uma vez
EspaçoO(V)Contagens de grau de entrada + conjunto pronto + ordem
RequerUm DAGCiclos não têm ordenação topológica
ResultadoNão únicoMuitas ordens válidas podem existir

Passo a passo (algoritmo de Kahn)

PassoO que acontece
1Calcular o grau de entrada (número de arestas de entrada) de cada nó.
2Reunir todos os nós com grau de entrada 0 em um conjunto pronto.
3Pegar um nó pronto e acrescentá-lo à ordem de saída.
4Decrementar o grau de entrada de cada um de seus sucessores.
5Todo sucessor que chegar a grau de entrada 0 entra no conjunto pronto.
6Repetir até o conjunto pronto ficar vazio.

Exemplo resolvido

Ordenando o DAG com arestas A→C, B→C, C→D, C→E, D→F, E→F (graus de entrada iniciais A:0 B:0 C:2 D:1 E:1 F:2):

PassoConjunto prontoOrdemAção
0{A, B}[]A e B começam com grau de entrada 0, então ambos estão prontos.
1{B}[A]Emitir A; sua aresta A→C reduz o grau de entrada de C de 2 → 1.
2{C}[A, B]Emitir B; sua aresta B→C reduz C de 1 → 0, então C fica pronto.
3{D, E}[A, B, C]Emitir C; as arestas C→D e C→E reduzem D e E a 0, ambos ficam prontos.
4{E}[A, B, C, D]Emitir D; sua aresta D→F reduz o grau de entrada de F de 2 → 1.
5{F}[A, B, C, D, E]Emitir E; sua aresta E→F reduz F de 1 → 0, então F fica pronto.
6{}[A, B, C, D, E, F]Emitir F; o conjunto pronto está vazio e os 6 nós estão ordenados: concluído.

Quando usar a ordenação topológica

Use quandoEvite quando
Você precisa de uma ordem que respeite dependências (etapas de compilação, instalação de pacotes, pré-requisitos de cursos).O grafo é não dirigido: a ordem topológica só é definida para grafos dirigidos.
O grafo é um DAG e você quer qualquer ordenação linear válida.O grafo pode conter ciclos e você ainda precisa de uma ordem total (não existe nenhuma).
Você quer detectar ciclos de forma barata: uma ordenação topológica que falha prova que existe um.Você precisa da ordem mais curta ou ótima segundo algum peso; a ordenação topológica simples ignora pesos.
Você processará a ordem uma única vez em O(V + E).As arestas mudam constantemente e você precisa reordenar a cada atualização, onde uma estrutura incremental encaixa melhor.

Código de Topological Sort

Uma implementação limpa e executável de Topological Sort em Python, JavaScript, Java, C++, C. Escolha uma linguagem, copie o código ou abra-o já carregado no Playground da Coddy.

Código de Topological Sort em Python

Python
1from collections import deque2
3
4def topological_sort(graph):5    # Kahn's algorithm: repeatedly remove nodes with no incoming edges6    in_degree = {node: 0 for node in graph}7    for node in graph:8        for neighbor in graph[node]:9            in_degree[neighbor] += 110    queue = deque(node for node in graph if in_degree[node] == 0)11    order = []12    while queue:13        node = queue.popleft()14        order.append(node)15        for neighbor in graph[node]:16            in_degree[neighbor] -= 117            if in_degree[neighbor] == 0:18                queue.append(neighbor)19    if len(order) != len(graph):20        raise ValueError("Graph has a cycle, no topological order")21    return order22
23
24graph = {25    "shirt": ["tie", "jacket"],26    "tie": ["jacket"],27    "pants": ["shoes", "jacket"],28    "socks": ["shoes"],29    "shoes": [],30    "jacket": [],31}32
33print(" -> ".join(topological_sort(graph)))
Execute este código no Playground de Python

Perguntas frequentes sobre a ordenação topológica

Para que serve uma ordenação topológica?
Ela ordena as tarefas de modo que cada dependência venha antes daquilo que precisa dela. Usos reais incluem sistemas de compilação e gerenciadores de pacotes (compilar dependências primeiro), o agendamento de cursos com pré-requisitos e a ordem de avaliação de fórmulas em planilhas.
Qual é a complexidade de tempo da ordenação topológica?
Tanto o algoritmo de Kahn quanto a abordagem baseada em DFS executam em tempo O(V + E), pois cada nó é processado uma vez e cada aresta é examinada uma vez. Eles usam O(V) de espaço adicional.
Por que a ordenação topológica exige um DAG?
Um ciclo dirigido cria uma contradição: se a deve vir antes de b e b deve vir antes de a, nenhuma ordem linear satisfaz ambas. Por isso, uma ordenação topológica existe se e somente se o grafo for um grafo acíclico dirigido. O algoritmo de Kahn detecta um ciclo quando termina antes de emitir todos os nós.
Qual é a diferença entre o algoritmo de Kahn e a ordenação topológica por DFS?
O algoritmo de Kahn é iterativo e semelhante ao BFS: ele remove repetidamente os nós com grau de entrada 0, tornando explícitas a detecção de ciclos e a ordenação. A abordagem DFS visita os nós recursivamente e antepõe cada um à ordem quando sua recursão termina, produzindo o inverso dos tempos de finalização. Ambos são O(V + E); o de Kahn evita recursão profunda e expõe o conjunto pronto naturalmente, enquanto o DFS costuma ser mais curto de escrever.
Quando devo usar a ordenação topológica em vez de uma ordenação normal?
Use a ordenação topológica quando a ordem for definida por dependências entre itens em vez de por uma chave comparável. Uma ordenação por comparação como o mergesort O(n log n) ordena por valor; a ordenação topológica ordena por arestas de «deve vir antes» e, ao contrário de uma ordenação por comparação, pode produzir muitas respostas válidas para a mesma entrada.
O resultado de uma ordenação topológica é único?
Normalmente não. Sempre que dois ou mais nós estiverem prontos (grau de entrada 0) ao mesmo tempo, você pode emiti-los em qualquer ordem, então a maioria dos DAGs admite várias ordenações topológicas válidas. A ordem é única apenas quando há exatamente um nó pronto em cada passo, o que ocorre quando o DAG forma uma única cadeia (um caminho hamiltoniano).
Coddy programming languages illustration

Domine algoritmos com a Coddy

COMEÇAR