자료구조
C#) 다익스트라(Dijkstra) 알고리즘
HSH12345
2023. 3. 5. 01:25
다익스트라(Dijkstra) 알고리즘이란?
그래프의 한 정점(노드)에서 다른 정점까지의 최단 경로를 구하는 알고리즘으로 첫 번째 정점에서 목표 정점까지 존재하는 모든 정점을 방문하여 목표정점까지 최단 거리를 구한다. 아래 이미지를 활용하여 다익스트라 알고리즘에 대해 쉽게 이해할 수 있다.
위 이미지의 A정점에서 B정점까지 도달하는 최단거리는 10이다. 그렇다면 A정점에서 C정점까지 도달할 수 있는 최단 거리는 30일까? 그렇지 않다. C가지 도달할 수 있는 경우의 수를 따져본다면, A에서 C로 바로 가는 방법도 있지만 A에서 D를 방문하여 거리를 탐색하고 C를 방문할 수도있다. 후자의 경우 경로의 길이는 20으로 30보다 짧은 거리인 것을 알 수 있다. 이런 식으로 출발 정점에서 목표한 정점까지 연결된 모든 정점들을 방문하여 도달가능한 모든 경우의 수를 탐색하고 최단 경로를 구하는 알고리즘이 다익스트라 알고리즘이다.
구현 방식
위 이미지의 A정점에서 F정점까지의 최단경로를 다익스트라 알고리즘을 통해 찾는다면 아래와 같다.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Dijkstra
{
class Program
{
public enum eNode
{
A, B, C, D, E, F
}
static void Main(string[] args)
{
Graph graph = new Graph(6);
graph.AddEdge((int)eNode.A, (int)eNode.B, 10);
graph.AddEdge((int)eNode.A, (int)eNode.D, 15);
graph.AddEdge((int)eNode.A, (int)eNode.C, 30);
graph.AddEdge((int)eNode.B, (int)eNode.E, 20);
graph.AddEdge((int)eNode.C, (int)eNode.F, 5);
graph.AddEdge((int)eNode.D, (int)eNode.C, 5);
graph.AddEdge((int)eNode.D, (int)eNode.F, 20);
graph.AddEdge((int)eNode.E, (int)eNode.F, 20);
graph.AddEdge((int)eNode.F, (int)eNode.D, 20);
List<int> shortestPath = graph.Dijkstra((int)eNode.A, 5);
foreach(int node in shortestPath)
{
Console.Write("{0} ", (eNode)node);
}
}
}
class Graph
{
private int[,] adj;
private int size;
List<int> path = new List<int>();
public Graph(int size)
{
this.size = size;
this.adj = new int[this.size, this.size];
}
public void AddEdge(int a, int b, int dist)
{
this.adj[a, b] = dist;
}
public List<int> Dijkstra(int start, int dest)
{
bool[] visited = new bool[this.size];
int[] distance = new int[this.size];
int[] parent = new int[this.size];
for(int i = 0; i < distance.Length; i++)
{
distance[i] = Int32.MaxValue;
}
distance[start] = 0;
parent[start] = start;
while (true)
{
int now = -1;
int closest = Int32.MaxValue;
for(int i = 0; i < this.size; i++)
{
if (visited[i]) continue;
if (distance[i] == Int32.MaxValue) continue;
if(distance[i] < closest)
{
closest = distance[i];
now = i;
}
}
if (now == -1) break;
visited[now] = true;
for(int next = 0; next < this.size; next++)
{
if (this.adj[now, next] == 0) continue;
if (visited[next]) continue;
int nextDist = distance[now] + this.adj[now, next];
if(nextDist < distance[next])
{
distance[next] = nextDist;
parent[next] = now;
}
}
}
return this.CalcPathFromParent(parent, dest);
}
private List<int> CalcPathFromParent(int[] parent, int dest)
{
Console.WriteLine("{0}까지 최단 경로 : ", dest);
while(parent[dest] != dest)
{
this.path.Add(dest);
dest = parent[dest];
}
this.path.Add(dest);
this.path.Reverse();
return this.path;
}
}
}