You will be fine

<알고리즘> 1. 다익스트라 JAVA

by BFine
반응형

가. 무엇인가

 a. 최단경로

  -  시작정점부터 모든 정점으로 가는 최단경로를 구하는 알고리즘 

     => 가중치가 양수일 경우에만 사용가능

  -  진행

      0. 모든 정점이 가지고 있는 가중치합(시작정점부터 도착정점까지의 최단경로)을 INF(엄청큰값) 초기화한다.

      1. 현재 정점(동그리미)이 가진 간선들중 가장 최소값을 가지는 간선의 정점을 방문한다.

          => 이때 방문 정점이 가지고 있는 가중치합은 여러 정점을 거쳐왔을수도 있다.

      2. 현재 경로의 가중치합과 방문정점이 가지고 있는 가중치의 합을 비교해서 최소값으로 업데이트한다. 

      3. 현재 시점에서 가중치합이 더 작았다면 방문정점에서 다시 1번을 수행한다. 

 

나. 구현하기 

 a. 배열

public class 다익스트라 {

    public static void main(String[] args) {
        int N = 5;
        List<Edge>[] path = new LinkedList[N];
        for(int i = 0; i < N; i++) {
           path[i] = new LinkedList<>();
        }
        path[0].add(new Edge(2,1));
        path[0].add(new Edge(1,4));
        path[1].add(new Edge(3,1));
        path[2].add(new Edge(1,2));
        path[4].add(new Edge(0,2));
        path[4].add(new Edge(2,3));
        path[4].add(new Edge(3,7));
        new 다익스트라().최단경로(4, path);
    }
    
    public void 최단경로(int start, List<Edge>[] path){

        int N = path.length;
        boolean[] visited = new boolean[N];
        int[] dist = new int[N];  // 시작점과 정점의 최단경로 가중치
        int[] prev = new int[N]; // 이전 방문 정점
        Arrays.fill(dist,INF);
        Arrays.fill(prev,-1);

        dist[start] = 0;
        // 시작을 가장작은 경로값을 가지는 것이므로 0으로 초기화

        prev[start] = -1;


        for(int i = 0; i < N; i++) {
            // 모든 정점을 방문하는 순간 끝이므로 N번 반복
            int min = INF;
            int minVertex = -1;

            // 가장 최소가 되는 정정부터 탐색
            for(int j = 0; j < N; j++) {
                if(!visited[j] &&  dist[j] < min){
                    min = dist[j];
                    minVertex = j;
                }
            }

            visited[minVertex] = true;

            for(Edge adjEdge : path[minVertex]){
                int newDist = dist[minVertex] + adjEdge.weight;
                // 이전까지의 가중치 + 가려고하는 정점의 가중치

                int currentDist = dist[adjEdge.vertex];

                if(!visited[adjEdge.vertex] && newDist < currentDist){
                    // 경로 업데이트
                    dist[adjEdge.vertex] = newDist;
                    prev[adjEdge.vertex] = minVertex;
                }
            }
        }

        for(int i = 0; i < N; i++) {
            int k = i;
            List<Integer> order = new ArrayList<>();
            while(k != -1){
                order.add(k);
                k = prev[k];
            }
            Collections.reverse(order);
            for(int v : order ){
                System.out.print(v+" -> ");
            }
            System.out.println();
        }

    }

    public int INF = Integer.MAX_VALUE;

    private static class Edge {
        int vertex;
        int weight;

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

    }
}

 

 b. 우선순위큐

  -  경로가 최소인 부분을 찾을때 우선순위 큐를 사용해서 찾을 수도 있다.

public class 다익스트라_우선순위큐 {

    public static void main(String[] args) {

        int N = 5;
        List<Edge>[] path = new LinkedList[N];
        for(int i = 0; i < N; i++) {
            path[i] = new LinkedList<>();
        }
        path[0].add(new Edge(2, 1));
        path[0].add(new Edge(1, 4));
        path[1].add(new Edge(3, 1));
        path[2].add(new Edge(1, 2));
        path[4].add(new Edge(0, 2));
        path[4].add(new Edge(2, 3));
        path[4].add(new Edge(3, 7));
        new 다익스트라_우선순위큐().최단경로(4, path);
    }
    public int INF = Integer.MAX_VALUE;

    public void 최단경로(int start, List<Edge>[] path){
        int N = path.length;
        boolean[] visited = new boolean[N];
        int[] prev = new int[N];
        int[] dist = new int[N];
        Arrays.fill(prev,-1);
        Arrays.fill(dist,INF);

        dist[start] = 0;

        Queue<Edge> queue = new PriorityQueue<>();
        queue.add(new Edge(start,dist[start]));

        for(int i = 0; i < N; i++) {
            Edge minVertex = queue.poll();

            if(visited[minVertex.vertex]) continue;
            visited[minVertex.vertex] = true;

            for(Edge adj : path[minVertex.vertex] ){
                int newDist = dist[minVertex.vertex] + adj.weight;
                int current = dist[adj.vertex];
                if(!visited[adj.vertex] && newDist < current){
                    dist[adj.vertex] = newDist;
                    prev[adj.vertex] = minVertex.vertex;
                    queue.add(new Edge(adj.vertex,newDist));
                }
            }
        }

        System.out.println(Arrays.toString(dist));
        for(int i = 0; i < N; i++) {
            int k = i;
            List<Integer> order = new ArrayList<>();
            while(k != -1){
                order.add(k);
                k = prev[k];
            }
            Collections.reverse(order);
            for(int v : order ){
                System.out.print(v+" -> ");
            }
            System.out.println();
        }

    }
    private static class Edge implements Comparable<Edge>{
        int vertex;
        int weight;

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

        @Override
        public int compareTo(Edge o) {
            return Integer.compare(this.weight,o.weight);
        }
    }
}

 

참고 : www.aladin.co.kr/shop/wproduct.aspx?ItemId=115240038

 

자바와 함께하는 자료구조의 이해

자료구조의 이해에 있어 가장 기본적이고 공통된 부분을 발췌, 정리함과 동시에 최신 주제인 좌편향 레드블랙트리, Tim Sort와 이중피벗퀵정렬, 소셜네트워크분석의 응용을 추가하였다. 자료구조

www.aladin.co.kr

반응형

'알고리즘 > 이론' 카테고리의 다른 글

<알고리즘> 4. 세그먼트트리 JAVA  (0) 2021.04.19
<알고리즘> 3. LRU 캐시 JAVA  (0) 2021.04.19
<알고리즘> 2. 위상정렬 JAVA  (0) 2021.04.17

블로그의 정보

57개월 BackEnd

BFine

활동하기