다익스트라 알고리즘

 

  • 한 정점에서 다른 모든 정점까지의 최단 경로를 구하는 알고리즘

  • 겨올탐색, 네트워크 라우팅 등 분야에서 활용될 수 있음

  • 그리디 기법

 

 

 

 

동작 원리

1. 출발 정점에서 시작. 인접 정점 중 가장 짧은 경로를 갖는 정점을 선택

 

2. 선택 정점에서 다른 인접 정점까지의 거리를 계산하고, 이전에 계산된 거리와 비교해 더 짧은 경로가 발견되면 해당 경로로 업데이트.

 

3. 같은 방법으로 최단 경로를 찾을 때까지 진행

 

 

 

 

 

장점

  • 탐색속도: 모든 간선이 음수가 아닐 때 빠른 탐색 속도로 경로 탐색 가능

  • 우선순위 큐를 활용해 시간 복잡도 절감 가능

 

단점

  • 음수 가중치가 있는 그래프에서는 작동 X

  • 배열을 활용한 방법의 경우 간선이 많을수록 성능 저하될 수 있음

 

 

 

구현

1.방문체크배열(visited), 인접배열(adjArr), 시작점으로부터의 거리(dist)를 저장할 배열이 필요

 

2. dist배열을 모두 무한대로 설정하고, 탐색 시작할 정점만 0으로 변경

 

3. 현재 방문하지 않은 정점 중 가장 짧은 거리를 가진 정점을 선택

 

4. 인접배열을 통해 탐색하고자 하는 정점과 인접한 정점들의 거리를 더 짧은 거리로 업데이트

 

 

 

 

 

<배열을 활용한 방법>

 

import java.util.Arrays;

public class DijkstraArray {

    // 정점의 개수 V, 무한대 값으로 사용할 상수
    static final int V = 5;
    static final int INF = Integer.MAX_VALUE;

    // 다익스트라 알고리즘을 배열 기반으로 구현
    public static void dijkstra(int[][] adjMatrix, int start) {
        // 각 정점까지의 최소 거리를 저장하는 배열
        int[] dist = new int[V];
        // 방문 여부를 저장하는 배열
        boolean[] visited = new boolean[V];

        // 초기화: 모든 거리를 무한대로 설정하고, 시작 정점의 거리를 0으로 설정
        Arrays.fill(dist, INF);
        dist[start] = 0;

        // 모든 정점을 하나씩 처리
        for (int i = 0; i < V - 1; i++) {
            // 방문하지 않은 정점 중 가장 거리가 짧은 정점을 선택
            int u = selectMinVertex(dist, visited);

            // 선택된 정점을 방문 처리
            visited[u] = true;

            // 인접한 정점들의 거리를 업데이트
            for (int v = 0; v < V; v++) {
                if (!visited[v] && adjMatrix[u][v] != 0 && dist[u] != INF && dist[u] + adjMatrix[u][v] < dist[v]) {
                    dist[v] = dist[u] + adjMatrix[u][v];
                }
            }
        }

        // 최종 최단 경로 출력
        printSolution(dist);
    }

    // 방문하지 않은 정점 중 최소 거리를 가진 정점을 선택
    public static int selectMinVertex(int[] dist, boolean[] visited) {
        int min = INF, minIndex = -1;

        for (int v = 0; v < V; v++) {
            if (!visited[v] && dist[v] < min) {
                min = dist[v];
                minIndex = v;
            }
        }
        return minIndex;
    }

    // 최단 경로를 출력하는 메서드
    public static void printSolution(int[] dist) {
        System.out.println("정점별 최단 거리:");
        for (int i = 0; i < V; i++) {
            System.out.println(i + " -> " + dist[i]);
        }
    }

    public static void main(String[] args) {
        // 그래프의 인접 행렬 표현
        int[][] adjMatrix = {
            { 0, 10, 0, 30, 100 },
            { 10, 0, 50, 0, 0 },
            { 0, 50, 0, 20, 10 },
            { 30, 0, 20, 0, 60 },
            { 100, 0, 10, 60, 0 }
        };

        // 다익스트라 알고리즘 실행 (시작 정점: 0)
        dijkstra(adjMatrix, 0);
    }
}

 

 

<우선순위큐를 활용한 방법>

import java.util.*;

public class DijkstraPriorityQueue {

    static final int V = 5;
    static final int INF = Integer.MAX_VALUE;

    // 간선 클래스 (정점과 가중치)
    static class Edge implements Comparable<Edge> {
        int vertex, weight;

        Edge(int vertex, int weight) {
            this.vertex = vertex;
            this.weight = weight;
        }

        // 가중치 기준으로 우선순위 큐에서 정렬
        public int compareTo(Edge other) {
            return this.weight - other.weight;
        }
    }

    // 다익스트라 알고리즘을 우선순위 큐로 구현
    public static void dijkstra(int[][] adjMatrix, int start) {
        // 최소 거리를 저장하는 배열
        int[] dist = new int[V];
        // 우선순위 큐
        PriorityQueue<Edge> pq = new PriorityQueue<>();

        // 초기화: 모든 거리를 무한대로 설정하고, 시작 정점의 거리를 0으로 설정
        Arrays.fill(dist, INF);
        dist[start] = 0;

        // 시작 정점을 우선순위 큐에 삽입
        pq.add(new Edge(start, 0));

        // 우선순위 큐가 빌 때까지 반복
        while (!pq.isEmpty()) {
            Edge current = pq.poll();  // 현재 정점
            int u = current.vertex;

            // 인접한 정점들의 거리 업데이트
            for (int v = 0; v < V; v++) {
                if (adjMatrix[u][v] != 0 && dist[u] != INF && dist[u] + adjMatrix[u][v] < dist[v]) {
                    dist[v] = dist[u] + adjMatrix[u][v];
                    pq.add(new Edge(v, dist[v]));
                }
            }
        }

        // 최종 최단 경로 출력
        printSolution(dist);
    }

    // 최단 경로를 출력하는 메서드
    public static void printSolution(int[] dist) {
        System.out.println("정점별 최단 거리:");
        for (int i = 0; i < V; i++) {
            System.out.println(i + " -> " + dist[i]);
        }
    }

    public static void main(String[] args) {
        // 그래프의 인접 행렬 표현
        int[][] adjMatrix = {
            { 0, 10, 0, 30, 100 },
            { 10, 0, 50, 0, 0 },
            { 0, 50, 0, 20, 10 },
            { 30, 0, 20, 0, 60 },
            { 100, 0, 10, 60, 0 }
        };

        // 다익