다익스트라 알고리즘 (Dijkstra’s Algorithm)

다익스트라 알고리즘(Dijkstra’s Algorithm)은 그래프의 한 정점에서 다른 모든 정점까지의 최단 경로를 찾는 알고리즘입니다.

음의 가중치가 없는 그래프에서만 동작하며 대표적인 최단 경로 탐색 알고리즘입니다.

다익스트라 알고리즘 예제

우선순위 큐 사용 예제

class PriorityQueue {
  constructor() {
    this.values = [];
  }

  enqueue(val, priority) {
    this.values.push({ val, priority });
    this.sort();
  }

  dequeue() {
    return this.values.shift(); // 최소값 우선
  }

  sort() {
    this.values.sort((a, b) => a.priority - b.priority);
  }

  isEmpty() {
    return this.values.length === 0;
  }
}

function dijkstra(graph, start) {
  const distances = {};
  const pq = new PriorityQueue();
  const previous = {};

  // 초기화
  for (let node in graph) {
    distances[node] = Infinity;
    previous[node] = null;
  }

  distances[start] = 0;
  pq.enqueue(start, 0);

  while (!pq.isEmpty()) {
    const { val: currentNode } = pq.dequeue();

    for (let neighbor of graph[currentNode]) {
      const { node: neighborNode, weight } = neighbor;
      const newDist = distances[currentNode] + weight;

      if (newDist < distances[neighborNode]) {
        distances[neighborNode] = newDist;
        previous[neighborNode] = currentNode;
        pq.enqueue(neighborNode, newDist);
      }
    }
  }

  return distances;
}

예제 그래프

const graph = {
  A: [{ node: "B", weight: 1 }, { node: "C", weight: 4 }],
  B: [{ node: "C", weight: 2 }, { node: "D", weight: 5 }],
  C: [{ node: "D", weight: 1 }],
  D: []
};

console.log(dijkstra(graph, "A"));
// 출력: { A: 0, B: 1, C: 3, D: 4 }

  • PriorityQueue는 간단한 배열 기반 구현입니다. 성능이 중요한 경우는 최소 힙(Min Heap)을 사용하는 게 더 효율적입니다.
  • distances 객체는 각 노드까지의 최단 거리를 저장합니다.
  • previous 객체를 이용하면 경로 추적도 할 수 있습니다.

다익스트라 알고리즘 설명

PriorityQueue는 다익스트라 알고리즘에서 가장 가까운 노드를 선택하기 위해 사용됩니다.

이번 예제에서는 배열 정렬을 사용하지만 성능이 중요한 상황에서는 최소 힙 구조를 쓰는 게 더 좋습니다.

distances는 A에서 각 노드까지의 최소 거리를 기록합니다.

previous는 각 노드에 도달했을 때의 이전 노드를 저장하며 이를 기반으로 최단 경로를 복원할 수 있습니다.

시작노드 거리만 0으로 설정하고 나머지는 무한대로 시작합니다.

while 루프에서는 우선순위 큐에서 현재 가장 가까운 노드를 꺼낸 후, 그 노드의 이웃 노드에 대해 거리 계산을 해보고 지금까지 알려진 거리보다 짧으면 갱신합니다.

갱신된 노드는 큐에 다시 넣어 탐색 대상이 되고 이 방법을 반복하여 모든 노드를 탐색했다면 distances에는 각 노드까지의 최단 거리가 남게됩니다.

용어 정리

  • 정점(Vertex): 노드
  • 간선(Edge): 노드 간 연결
  • 가중치(Weight): 간선에 부여된 비용
  • 최단 경로(Distance): 한 정점에서 다른 정점까지의 최소 비용 경로

기본 개념

  • 가장 가까운 정점부터 차례대로 최단 경로를 확정해 나가는 방식으로 탐욕적(Greedy) 기법에 기반을 둠
  • 방문하지 않은 정점들 중에서 현재까지의 거리가 가장 짧은 정점을 선택하고 이웃 노드들의 거리 값을 갱신

전제 조건

  • 가중치(간선 비용)는 0 이상의 정수여야 함 (음의 가중치가 있는 경우에는 벨만-포드 알고리즘 사용)
  • 그래프는 연결되어 있을 수도 있고 아닐 수도 있음
  • 우선순위 큐를 사용하면 시간 복잡도 개선 가능

다익스트라 알고리즘 단계 (우선순위 큐 사용)

입력:

  • 그래프 𝐺 = ( 𝑉 , 𝐸 )
  • 시작 정점 𝑠

초기화:

  1. 모든 정점의 거리를 무한대로 설정
  2. 시작 정점의 거리는 0으로 설정
  3. 우선순위 큐에 (거리, 정점) 형태로 삽입

반복:

  1. 큐에서 거리가 가장 짧은 정점 𝑢를 꺼냄
  2. 𝑢의 모든 이웃 정점 𝑣에 대해:
    • 현재까지의 거리 dist[𝑣]와
    • 𝑢를 거쳐 가는 거리 dist[𝑢] + 𝑤(𝑢, 𝑣)를 비교
    • 더 짧은 경로를 찾으면 갱신하고, 우선순위 큐에 갱신된 거리로 삽입

종료:

  • 모든 정점에 대해 최단 거리 계산이 완료되면 종료

시간복잡도

우선순위 큐를 힙(Heap)으로 구현할 경우:

𝑂((𝑉 + 𝐸) log 𝑉)

→ V는 정점 수, E는 간선 수

장점

  • 간단하고 직관적
  • 효율적 (우선순위 큐 사용 시)

단점

  • 음의 가중치가 있는 그래프에서는 사용 불가
  • 모든 정점에 대해 최단 경로를 구하므로 단일 목적지 탐색엔 비효율적임

관련 글

알고리즘 튜토리얼