728x90
개요
- 특정 노드에서 다른 모든 노드 간 최단 경로를 계산하는 알고리즘이다.
- 벨만-포드 알고리즘보다 효율적이다.
- 가중치에 음수가 없는 그래프에서만 사용할 수 있다.
- 벨만 포드처럼 각 노드까지의 거리를 INF로 초기화하고 탐색과정에서 값을 줄인다.
- 알고리즘의 각 단계에서는 아직 처리하지 않은 노드 중 거리가 가장 작은 노드를 먼저 선택하고, 해당 노드에서 시작하는 모든 간선을 보며 다른 노드까지의 거리를 줄일 수 있다면 줄인다.
- 음수 가중치가 없다고 전제하여 모든 간선을 단 한 번만 처리한다. 그래서 매우 효율적이다.
- 각 노드를 처리한 뒤에는 해당 노드까지의 거리가 절대 변하지 않는다.
- 음수 간선이 존재하면 사용할 수 없다.
구현
- 효율적인 구현을 위해서는 아직 처리하지 않은 노드 중 거리가 가장 짧은 노드를 효율적으로 찾아야 한다.
- 노드 선택을 log 시간에 구할 수 있는 우선순위 큐를 이용하여 처리 순서를 관리한다.
- 거리가 바뀔 때마다 해당 노드를 우선순위 큐에 추가한다.
- 그래프는 인접리스트의 형태로 저장된다.
- 알고리즘은 모든 노드를 탐색하며 진행되고, 각 노드에 연결된 간선에 대해서 값을 한 번씩만 우선순위 큐에 추가한다.
- 노드의 개수 n, 간선의 개수 m이면 시간복잡도는 O(n+m)이다.
Java
int INF = 무한, 알고리즘 구현 상 도출될 수 없는 큰 값으로 선언함.
int[] dist;
boolean[] visited;
PriorityQueue<Node> pq;
class Node implements Comparable<Node> {
int node;
int cost;
public Node() {
}
public Node(int node, int cost) {
this.node = node;
this.cost = cost;
}
@override
public int compareTo(Node o) {
return this.cost - o.cost;
}
}
...
int dijkstra(int start, int target) {
for(int i = 1; i <= n; i++) {
dist[i] = INF;
}
dist[x] = 0;
pq.offer(new Node(x, dist[x]));
while(!pq.isEmpty()) {
Node current = pq.poll();
int u = current.node;
if(u == target) {
return dist[u];
}
if(dist[u] < current.cost) {
continue;
}
if(!visited[u]) {
visited[u] = true;
foreach(Node next : adjList[u]) {
int v = next.node;
int w = next.cost;
if(dist[v] > dist[u] + w) {
dist[v] = dist[u] + w;
pq.offer(new node(v, dist[v]));
}
}
}
}
return -1;
}
'Problem Solving > 알고리즘' 카테고리의 다른 글
최소 신장 트리 : 크루스칼(Kruskal) (0) | 2021.04.29 |
---|---|
최단 경로 알고리즘 : 플로이드-워셜(Floyd-Warshall) (0) | 2021.04.23 |
최단 경로 알고리즘 : 벨만-포드(Bellman-Ford) (0) | 2021.04.23 |
그래프 탐색 알고리즘 : 너비 우선 탐색(Breadth-First Search) (0) | 2021.04.23 |
그래프 탐색 알고리즘 : 깊이 우선 탐색(Depth-First Search) (0) | 2021.04.23 |