간선에 음수가 아닌 가중치(거리·비용·시간)가 있는 그래프에서, 한 정점으로부터 다른 모든 정점까지의 최단 경로를 구하는 알고리즘. 에츠허르 데이크스트라(Edsger W. Dijkstra)가 1956년에 고안했다. 지도 길찾기와 네트워크 라우팅의 바탕이다.
방식
- 시작 정점의 거리는 0, 나머지는 무한대로 둔다
- 아직 확정되지 않은 정점 중 거리가 가장 짧은 것을 꺼낸다
- 그 정점의 이웃마다 "꺼낸 정점까지 거리 + 간선 가중치"가 지금 아는 거리보다 짧으면 갱신하고, 어디서 왔는지(이전 정점)를 기록한다
- 모든 정점이 확정될 때까지 2~3을 반복한다
- 이전 정점 기록을 끝에서부터 거슬러 올라가면 경로가 나온다
// 2단계의 "가장 짧은 것 꺼내기"를 우선순위 큐로
pq.enqueue(start, 0)
while (!pq.isEmpty()) {
const { value: v, priority: d } = pq.dequeue()
if (d > dist[v]) continue // 이미 더 짧은 길을 찾은 낡은 항목
for (const { node, weight } of graph[v]) {
const nd = d + weight
if (nd < dist[node]) { dist[node] = nd; prev[node] = v; pq.enqueue(node, nd) }
}
}복잡도
2단계를 매번 전체 훑기로 하면 O(V²), 우선순위 큐(이진 힙)로 하면 O((V + E) log V)다.
- 음수 가중치가 있으면 틀린 답을 낸다. 그때는 벨만-포드 알고리즘(Bellman-Ford Algorithm)을 쓴다
- 가중치가 모두 같다면 더 단순한 너비 우선 탐색 (BFS)로 충분하다
- 목적지 방향으로 추정치를 더해 탐색 범위를 줄이면 A* 알고리즘(A* Search Algorithm)이 된다