Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 싸피 합격
- 세마포어란?
- 프록시서버
- 세마포어와 뮤텍스
- Proxy Server
- 동기화
- 싸피 면접 후기
- 클라우드 서버
- 호스팅
- Proxy
- 서버 호스팅
- 웹 호스팅
- SSAFY
- Dijkstra Algorithm
- 뮤텍스
- 싸피
- 프록시
- 뮤텍스란?
- 다익스트라 알고리즘
- 호스팅이란?
- 플로이드 와샬
- 세마포어
- 삼성 청년 SW 아카데미
- 최단 경로
- Synchronization
- 플로이드 워셜
- 다익스트라
- floyd-warshall
- 세마포어와 뮤텍스의 차이
Archives
- Today
- Total
어제의 나보다 성장한 오늘의 나
다익스트라 알고리즘(Dijkstra Algorithm) 본문
다익스트라 알고리즘이란?
음의 가중치가 없는 그래프의 한 정점에서 모든 정점까지의 최단거리를 각각 구하는 알고리즘 (최단 경로 문제, Shortest Path Problem)이다.
그래프 방향의 유무는 상관없으나, 간선(Edge)들 중에 단 하나라도 가중치가 음수이면 이 알고리즘은 사용할 수 없다.
말 그대로 최단거리에 관하여 논하는 문제이기 때문이다.
과정
간단한 로직을 살펴보면
- 출발 노드를 지정한다.
- 출발 노드를 기준으로 각 노드의 최소 비용을 저장한다.
- 방문하지 않은 노드 중에서 가장 비용이 적은 노드를 선택한다.
- 해당 노드를 거쳐서 특정한 노드로 가는 경우를 고려하여 최소 비용을 을 갱신한다.
- 3~4번을 반복한다.
그림으로 살펴 보겠다.
- 먼저 최단 경로를 저장하는 배열의 초기는 무한대이다.
- 1번 정점에서 시작해 모든 정점들까지의 최단 경로를 구한다고 가정한다.
- 당연하게 출발 노드는 1로 설정되고 0을 저장한다.
- 1번의 인접 정점들을 살피고 간선 가중치로 모두 업데이트된다.
- distance[특정 정점]과 distance[1] + (1번 정점과 특정 정점 사이의 가중치) 를 비교해 더 작은 값으로 갱신해준다.
- 다음은 아직 방문하지 않은 노드 중에 distance의 가장 작은 값을 가지는 5번 노드를 선택한다.
- 1번 노드는 방문했기 때문에 넘어간다.
- 4번 노드의 값이 distance[특정 정점] (현재 값 9) 과 distance[1] + (1번 정점과 특정 정점 사이의 가중치) ( 갱신하는 값 3) 갱신된다.
- 끝까지 구한다면 위에 보이는 표과 같이 1에서부터 각 노드까지의 최단경로가 구해진다.
- 1번 노드에서 5번 노드까지의 최단 경로는 distance[5]를 보면 되기 때문에 1이다
다음은 직접 자바 코드로 짜 본 다익스트라 알고리즘이다. (우선순위 큐로)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.PriorityQueue;
import java.util.StringTokenizer;
public class pqDijkstraTest {
static class Vertex implements Comparable<Vertex> {
int no, totalDistance; // totalDistance : 출발지에서 자신까지 오는 최단거리
public Vertex(int no, int totalDistance) {
super();
this.no = no;
this.totalDistance = totalDistance;
}
@Override
public int compareTo(Vertex o) {
return this.totalDistance - o.totalDistance; // totalDistance가 작은 비용이 우선적으로 처리
}
}
public static void main(String[] args) throws NumberFormatException, IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int V = Integer.parseInt(br.readLine());
int start = 0;
int end = V - 1;
final int INFINITY = Integer.MAX_VALUE;
int[][] matrix = new int[V][V];
int[] distance = new int[V]; // 출발지에서 자신까지 오는 최단거리
boolean[] visited = new boolean[V];
for (int i = 0; i < V; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
for (int j = 0; j < V; j++) {
matrix[i][j] = Integer.parseInt(st.nextToken());
}
}
PriorityQueue<Vertex> pQueue = new PriorityQueue<Vertex>();
Arrays.fill(distance, INFINITY);
distance[start] = 0;
pQueue.offer(new Vertex(start, distance[start]));
Vertex current = null;
while(!pQueue.isEmpty()) {
// 1단계 : 방문하지 않은 정점들 중에 출발지에서 자신까지 오는 비용이 최단인 정점을 고려할 경유지로 선택
current = pQueue.poll();
if(visited[current.no]) continue; // PQ에 남아있던 totalDistance의 최소비용보다 더 큰 상태
visited[current.no] = true;
if(current.no == end) break;
// 2단계 : 선택된 current 정점을 경유지로 해서 아직 방문하지 않은 다른 정점으로의 최단거리 비용 계산하여 유리하면 update
for(int j =0; j<V; j++) {
// min ==> distance[current]
if(!visited[j] && matrix[current.no][j] !=0
&&distance[j] > current.totalDistance + matrix[current.no][j]) {
distance[j] = current.totalDistance + matrix[current.no][j];
pQueue.offer(new Vertex(j, distance[j]));
}
}
}
System.out.println(distance[end]);
}
}
'공부 > 알고리즘' 카테고리의 다른 글
[알고리즘] 에라토스테네스의 체 ( 소수 구하기 ) (0) | 2021.06.04 |
---|---|
플로이드 와샬(Floyd-Warshall) (0) | 2021.04.08 |
위상정렬 (Topological Sort) (0) | 2021.04.04 |
유클리드 호제법 - 최소공약수, 최대공배수 (0) | 2021.04.04 |
Comments