Menu
Coddy logo textTech

Algoritmo de Dijkstra

Última atualização

O algoritmo de Dijkstra encontra o caminho mais curto de um nó de origem até todos os outros nós de um grafo com pesos de aresta não negativos. Ele mantém uma distância tentativa para cada nó, fixa repetidamente o nó não fixado com a menor distância tentativa e relaxa suas arestas, atualizando a distância de um vizinho sempre que uma rota mais curta através do nó atual é encontrada. Pressione reproduzir acima para ver as distâncias caírem à medida que cada nó é fixado.

A ideia central é gulosa: uma vez escolhido o nó não fixado mais próximo, sua distância é definitiva, porque qualquer outra rota até ele teria de passar por um nó que já está mais distante. Com uma fila de prioridade baseada em heap binário, Dijkstra é executado em tempo O((V + E) log V). Ele requer pesos não negativos: use Bellman-Ford se as arestas puderem ser negativas.

Complexidade de tempo e espaço

ImplementaçãoComplexidadeNotas
Heap binárioO((V + E) log V)A escolha comum e prática
Varredura de arrayO(V²)Mais simples; adequado para grafos densos
EspaçoO(V)Distâncias + fila de prioridade
RequerPesos não negativosArestas negativas quebram a escolha gulosa

Passo a passo

PassoO que acontece
1Defina a distância da origem como 0 e todas as outras como infinito.
2Escolha o nó não fixado com a menor distância tentativa.
3Marque-o como fixado: sua distância mais curta agora é definitiva.
4Para cada vizinho, calcule distância-através-do-atual + peso da aresta.
5Se for menor que a distância atual do vizinho, relaxe-a.
6Repita até fixar todos os nós alcançáveis.

Exemplo resolvido

Caminhos mais curtos a partir da origem A no grafo com arestas A-B=4, A-C=1, C-B=2, C-D=5, B-D=1:

PassoFixarDistânciasAção
0-A=0, B=∞, C=∞, D=∞Inicialize: origem A=0, todos os outros infinito.
1A (0)B=4, C=1, D=∞Relaxa as arestas de A: define B=4, C=1.
2C (1)B=3, D=6Através de C: B=1+2=3 supera 4; D=1+5=6.
3B (3)D=4Através de B: D=3+1=4 supera 6.
4D (4)A=0, C=1, B=3, D=4Fixa D; nada mais para relaxar. Concluído.

Quando usar o algoritmo de Dijkstra

Use quandoEvite quando
Todos os pesos de aresta são não negativosQualquer aresta pode ser negativa: use Bellman-Ford
Você precisa dos caminhos mais curtos de uma origem para todos os nósVocê precisa dos caminhos mais curtos entre todos os pares: Floyd-Warshall é mais simples
O grafo é ponderado e você quer distâncias exatasO grafo não é ponderado: um BFS simples é mais rápido e simples
Você tem um bom heap ou fila de prioridade disponívelVocê quer chegar rápido a um único destino com uma heurística: use A*

Código de Dijkstra's Algorithm

Uma implementação limpa e executável de Dijkstra's Algorithm 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 Dijkstra's Algorithm em Python

Python
1import heapq2
3
4def dijkstra(graph, start):5    dist = {node: float("inf") for node in graph}6    dist[start] = 07    pq = [(0, start)]8    while pq:9        d, node = heapq.heappop(pq)10        if d > dist[node]:11            continue  # stale entry, a shorter path was already found12        for neighbor, weight in graph[node]:13            new_dist = d + weight14            if new_dist < dist[neighbor]:15                dist[neighbor] = new_dist16                heapq.heappush(pq, (new_dist, neighbor))17    return dist18
19
20graph = {21    "A": [("B", 4), ("C", 1)],22    "B": [("D", 1)],23    "C": [("B", 2), ("D", 5)],24    "D": [("E", 3)],25    "E": [],26}27
28for node, d in dijkstra(graph, "A").items():29    print(f"A -> {node}: {d}")
Execute este código no Playground de Python

Perguntas frequentes sobre o algoritmo de Dijkstra

Qual é a complexidade de tempo do algoritmo de Dijkstra?
Com uma fila de prioridade baseada em heap binário, ele roda em O((V + E) log V). Uma versão simples que varre um array em busca do mínimo a cada passo é O(V²), que na verdade pode ser mais rápida em grafos densos. Ambas usam espaço O(V).
Por que Dijkstra não funciona com pesos de aresta negativos?
Dijkstra pressupõe que, uma vez fixado o nó não fixado mais próximo, essa distância é definitiva. Uma aresta negativa poderia criar depois um caminho mais curto até um nó já fixado, quebrando essa suposição. Para grafos com pesos negativos, use o algoritmo de Bellman-Ford.
Qual é a diferença entre Dijkstra e BFS?
BFS encontra os caminhos mais curtos contando arestas (cada peso de aresta é efetivamente 1), usando uma fila simples. Dijkstra generaliza isso para grafos ponderados sempre expandindo o nó com a menor distância total, usando uma fila de prioridade. Em um grafo não ponderado, ambos produzem os mesmos caminhos.
Qual é a diferença entre Dijkstra e a busca A*?
A* é Dijkstra mais uma heurística que estima a distância restante até um destino, de modo que direciona a busca para esse objetivo em vez de se expandir uniformemente em todas as direções. Quando a heurística é zero, A* se reduz exatamente a Dijkstra. Use A* quando tiver um único destino e uma boa heurística admissível; use Dijkstra quando precisar de distâncias para todos os nós.
Quando devo usar Dijkstra em vez de Bellman-Ford?
Use Dijkstra sempre que todos os pesos de aresta forem não negativos: é mais rápido, O((V + E) log V) contra O(V·E) do Bellman-Ford. Escolha Bellman-Ford apenas quando as arestas puderem ser negativas ou você precisar detectar ciclos negativos. Em grafos não negativos, Dijkstra é quase sempre a melhor escolha.
Dijkstra pode revisitar um nó depois de fixá-lo?
Não: uma vez que um nó é fixado, sua distância é definitiva e nunca é relaxada novamente. Um erro comum nas implementações com heap é deixar entradas obsoletas na fila de prioridade após a distância de um nó melhorar; você deve ignorar um nó retirado se ele já estiver fixado (sua distância retirada excede a distância registrada). Esquecer essa verificação ainda dá respostas corretas, mas desperdiça trabalho.
Coddy programming languages illustration

Domine algoritmos com a Coddy

COMEÇAR