컴퓨터 과학에서, '''데이크스트라 알고리즘'''() 또는 '''다익스트라 알고리즘'''은 도로 교통망 같은 곳에서 나타날 있는 그래프에서 꼭짓점 간의 최단 경로를 찾는 알고리즘이다. 알고리즘은 컴퓨터 과학자 에츠허르 데이크스트라가 1956년에 고안했으며 뒤에 발표했다. 알고리즘은 변형이 많다. 데이크스트라의 원래 알고리즘은 꼭짓점 간의 가장 짧은 경로를 찾는 알고리즘이지만, 일반적인 변형은 꼭짓점을 "소스" 꼭짓점으로 고정하고 그래프의 다른 모든 꼭짓점까지의 최단경로를 찾는 알고리즘으로 최단 경로 트리를 만드는 것이다. 그래프에서 주어진 소스 꼭짓점에 대해서, 데이크스트라 알고리즘은 노드와 다른 모든 꼭짓점 간의 가장 짧은 경로를 찾는다. 알고리즘은 어떤 꼭짓점에서 다른 도착점까지 가는 경로를 찾을 때, 도착점까지 가는 가장 짧은 경로가 결정되면 멈추는 식으로 사용할 있다. 예컨대 어떤 그래프에서, 꼭짓점들이 각각 도시를 나타내고, 변들이 도시 사이를 연결하는 도로의 길이를 나타낸다면, 데이크스트라 알고리즘을 통하여 도시 사이의 최단 경로를 찾을 있다. 따라서 최단 경로 알고리즘은 네트워크 라우팅 프로토콜에서 널리 이용되며, 특히 IS-IS (Intermediate System to Intermediate System)와 OSPF(Open Shortest Path First)에서 주로 사용된다. 또한 데이크스트라 알고리즘은 존슨 알고리즘 같은 알고리즘의 서브루틴으로 채택되었다. 데이크스트라의 원래 알고리즘은 우선순위 큐를 사용하지 않았기 때문에 시간 복잡도가 (는 꼭짓점의 개수이다)이다. 알고리즘의 개념은 에서도 사용된다. 최소 우선 큐에 기반한 알고리즘은 피보나치 힙으로 수행되며 시간복잡도는 때문에 (는 변의 개수이다)이다. 알고리즘은 알려진 제한 없는 음이 아닌 가중치를 가지는 무작위 유향 그래프에서의 단일 소스 최단 경로 알고리즘 점근적으로 가장 빠른 알고리즘이다. 하지만, 특별한 경우(제한이 있는 정수 가중치나 유향 비순환 그래프 등의 경우)에는 다른 으로 개선할 있다. 어떤 분야, 특히 인공 지능 분야에서, 데이크스트라 알고리즘이나 변형은 '''균일 비용 탐색'''으로 알려져 있으며 최상 우선 탐색의 일반적인 아이디어의 예시로 공식화 되어있다. == 역사 == 데이크스트라는 1956년에 네덜란드 국립 수학 정보과학 연구소에서 새로운 컴퓨터 ARMAC의 수용력을 입증하는 프로그래머로 일할 최단 경로 문제에 대해서 생각했다. 이제 해야 일은 컴퓨터를 다루지 않는 사람들도 이해할 있도록 문제와 (컴퓨터가 만들어낸)해법을 선택하는 것이었다. 그는 최단 거리 알고리즘을 고안하고, 이후 ARMAC에서 약간 단순화된 네덜란드 도시 64개(도시의 숫자를 표시하기 위해서 비트만 필요하도록 64를 선정했다)의 교통 지도에 대해서 수행했다. 뒤, 데이크스트라는 기관의 다음 컴퓨터를 작업하던 하드웨어 엔지니어들의 문제를 직면했다: 기계의 후면 패널에 있는 핀을 연결 필요한 전선의 개수를 최소화하는 것이다. 해법으로, 프림 최소 신장 트리 알고리즘으로 알려진 알고리즘을 재발견 했다(이전에는 Jarník에 의해 알려져 있었고, 또한 프림에 의해 재발견 되었었다). 데이크스트라는 알고리즘을 프림이 발표한 2년 뒤이고 Jarník이 발표한 29년 뒤인 1959년에 발표했다. == 알고리즘 == 파일:Dijkstras progress 모션 계획 문제에서 데이크스트라 알고리즘이 시작점(좌측 하단, 빨간색)에서 도착점(우측 상단, 초록색)까지의 경로를 찾는 도해. 꼭짓점은 "시험" 집합("미방문" 꼭짓점들의 집합)을 나타낸다. 채워진 꼭짓점은 방문한 꼭짓점으로, 색은 거리를 나타낸다: 초록색이 수록 가깝다는 의미이다. 다른 방향으로 있는 꼭짓점들은 균일하게 탐색되며, 데이크스트라 알고리즘이 휴리스틱을 0과 같게 사용하기 때문에 원형 파면으로 적거나 많게 나타난다. 시작할 꼭짓점은 '''초기점'''으로, '''꼭짓점 ''Y''의 거리'''를 '''초기점'''에서 ''Y''까지의 거리로 정의한다. 데이크스트라 알고리즘은 초기 거리 값을 부여하고, 단계를 거듭하며 개선시킬 것이며, 개선시키는 것을 '''간선 완화'''('''edge 한다. 모든 꼭짓점을 미방문 상태로 표시한다. ''미방문 집합''이라는 모든 미방문 꼭짓점의 집합을 만든다. 모든 꼭짓점에 시험적 거리 값을 부여한다: 초기점을 0으로, 다른 모든 꼭짓점을 무한대로 설정한다. 초기점을 현재 위치로 설정한다. 현재 꼭짓점에서 미방문 인접 꼭짓점을 찾아 ''시험적'' 거리를 현재 꼭짓점에서 계산한다. 새로 계산한 ''시험적'' 거리를 현재 부여된 값과 비교해서 작은 값을 넣는다. 예를 들어, 현재 꼭짓점 ''A''의 거리가 6이라고 표시되었고, 인접 꼭짓점 ''B''로 연결되는 변의 길이가 2라고 한다면, ''A''를 통한 ''B''까지의 거리는 8이 된다. 이전의 ''B''까지의 거리가 8보다 컸다면 8로 바꾸고, 그렇지 않다면 그대로 놔둔다. 만약 현재 꼭짓점에 인접한 모든 미방문 꼭짓점까지의 거리를 계산했다면, 현재 꼭짓점을 방문한 것으로 표시하고 ''미방문 집합''에서 제거한다. 방문한 꼭짓점은 이후에는 다시 방문하지 않는다. 꼭짓점 사이의 경로를 찾는 경우: 도착점이 방문한 상태로 표시되면 멈추고 알고리듬을 종료한다. 완전 순회 경로를 찾는 경우: ''미방문 집합''에 있는 꼭짓점들의 시험적 거리 최솟값이 무한대이면 이는 출발점과 미방문 집합 사이에 연결이 없는 경우이므로 멈추고 알고리즘을 종료한다. 아니면 시험적 거리가 가장 작은 다음 미방문 꼭짓점을 새로운 "현재 위치"로 선택하고 3단계로 되돌아간다. 경로를 계획하고 있을 때, 사실은 위에서 했던 것처럼 도착점이 "방문"한 상태가 때까지 기다릴 필요가 없다: 도착점이 "미방문" 꼭짓점들 가장 시험적 거리가 작아지면 (그리고 다음 "현재 위치"로 선택될 있다면) 알고리즘을 종료할 있다. == 설명 == 아래쪽 교차로가 현재 위치일 갱신되는 상황을 나타낸 그림이다. 교차로에는 현재까지의 최단 거리가 적혀있다. 현재 위치에서 이웃 교차로까지 5의 거리로 있다고 때, 이웃교차로에는 15의 거리로 도착할 있다. 왼쪽 교차로는 이미 다른 경로를 통해 13의 거리로 도착할 있으므로 갱신하지 않고, 오른쪽 교차로는 짧은 거리로 도착할 있으므로 갱신한다. 가운데 교차로는 방문하지 않은 교차로이므로 갱신한다. 과정은 현재 거리에 도로 길이를 더한 값과 교차로에 쓰여진 값을 비교해서 구할 있다. :'''''참고:''' 문단에서는 이해를 돕기 위해서 '''교차로''', '''도로''' 그리고 '''지도'''라는 용어를 사용했지만, 공식적인 용어는 각각 '''꼭짓점''', '''변''' 그리고 '''그래프'''이다.'' 도시의 지도에서 출발지와 목적지 사이의 가장 짧은 거리를 찾는다고 하자. 데이크스트라 알고리즘에서는 교차점마다 출발지로부터의 거리를 적어서 가장 짧은 거리를 찾는다. 데이크스트라 알고리즘에서는 우선 모든 교차점에 ''무한대''를 적어놓는다. 표시는 실제 거리가 무한대라는 뜻이 아니라 교차로에 가보지 않았다는 것을 의미한다. 변형된 데이크스트라 알고리즘에서는 ''표시되지 않음''을 써놓기도 한다. 다음으로는 모든 교차점을 표시할 때까지 반복한다. 우선 현재 위치를 정하고 시작점으로부터의 거리를 쓴다. 시작할 때의 현재 위치는 시작점이다. 그리고 시작점으로부터의 거리는 당연히 0이다. 다음 현재 위치와 연결되어있는 교차로들의 거리를 갱신한다. 현재 위치에는 시작점으로부터 가장 짧은 거리가 쓰여 있다. 현재 위치 쓰여 있는 거리를 이웃 교차로로 연결된 도로의 길이를 이웃 교차로에 쓰여 있는 거리를 라고 때, 이면 이웃 교차로에 '''''최단 거리는 이며 값은 로부터 계산되었다'''''라고 쓴다. 과정을 완화라고 한다. 현재 위치에서 연결된 모든 이웃 교차로에 대해 완화가 끝나면 현재 위치에 방문함이라고 적고 현재 위치에서 가장 가까운, 방문하지 않은 교차로로 이동한다. 방문표시가 교차로에는 항상 최단거리가 적혀있을 것이다. 만약 방문하지 않은 이웃 교차로가 없는 경우에는 현재 위치의 거리가 계산된 교차로로 돌아가서 가까운 방문하지 않은 교차로로 이동한다. 현재 위치가 목적지라면 탐색을 종료한 최단 거리를 바탕으로 최단 경로를 찾는다. 출발지를 제외한 모든 교차로에는 자신이 계산되어온 교차로가 쓰여 있을 것이다. 교차로를 부모 노드라고 한다. 목적지에서 부모 노드를 계속 따라가면 최단경로를 따라서 출발지에 도착하게 된다. 알고리즘은 목적지를 향해서 조사하지 않고, 목적지까지의 최단거리보다 짧은 교차로들을 모두 고려하기 때문에 최단 거리를 찾을 있게 된다. 하지만 모든 교차로를 고려한다는 특징으로 인해 데이크스트라 알고리즘은 특정한 지도에서 상대적으로 느리게 작동할 있다. == 의사 코드 == 다음 알고리즘에서, 코드 꼭짓점 집합 에서 가장 작은 값을 가지는 꼭짓점 찾는다. 인접한 꼭짓점인 연결하는 변의 길이 (둘 간의 거리)를 반환한다. 18번째 줄의 변수 루트 꼭짓점에서 통해서 인접 꼭짓점 까지 가는 경로의 길이이다. 경로가 현재 대해서 기록된 최단 경로보다 짧다면, 현재 경로를 경로로 대체한다. 배열은 소스까지 최단 경로를 찾기 위한 소스 그래프의 "다음" 꼭짓점을 나타내는 배열이다. 거리에 기반한 데이크스트라 알고리즘의 시연이다. 빨간색 선은 최단 경로이다. 다시 말해, ''u''와 ''u''를 연결하는 선이다. 파란 선은 경감이 이루어지는 위치를 나타낸다. 즉, ''v''와 ''Q''에 있는 꼭짓점 ''u''를 연결하는 선으로, 소스에서 ''v''까지 가는 짧은 경로를 나타낸다. '''function''' ''source''): create vertex set '''for each''' vertex ''v'' in ''Graph'': ''// 초기화'' dist''v'' INFINITY ''// 소스에서 v까지의 아직 모르는 길이'' prev''v'' UNDEFINED ''// 소스에서 최적 경로의 이전 꼭짓점'' add ''v'' to ''Q'' ''// 모든 노드는 초기에 Q에 속해있다 (미방문 집합)'' 10 dist''source'' ''//'' ''소스에서 소스까지의 길이'' 11 12 '''while''' ''Q'' is not empty: 13 ''u'' vertex in ''Q'' with min distu ''// 최소 거리를 갖는 꼭짓점'' 14 ''// 가장 먼저 선택한다'' 15 remove ''u'' from ''Q'' 16 17 '''for each''' neighbor ''v'' of ''u'': ''// v는 여전히 Q에 있다.'' 18 ''alt'' dist''u'' length(''u'', ''v'') 19 '''if''' ''alt'' 연산을 하는 대신에) 꼭짓점이 큐에 없다면 꼭짓점을 큐에 삽입해야 한다. 실제로 빠른 계산 시간을 얻기 위해서 다른 자료구조를 사용할 있다. == 정확성의 증명 == 데이크스트라 알고리즘은 방문한 노드에 쓰여진 숫자를 이용하여 귀납적으로 증명할 있다. 시작점에서 노드로 있는 경로가 있는 경우, 방문한 노드 대해, 시작점부터 까지 가장 짧은 거리이고, 방문하지 않은 노드 대해 시작점부터 까지 가장 짧을 것으로 추정되는 거리이다. 시작점에서 노드로 없는 경우가 없다면 노드까지의 거리는 무한대로 둔다. (참고: 방문하지 않은 정점 대해 실제 최단거리가 아니다.) 그래프에 시작점만 있는 경우, 위의 가설은 자명하며, 수학적 귀납법의 기저사례로 사용된다. 그렇지 않으면, 가정이 방문한 꼭짓점이 ''n-1''일 성립한다고 가정하자. 경우에, 모든 미방문 꼭짓점에서 가장 작은 대해서 만족하는 선택한다. 에서 까지의 가장 짧은 거리로 있다. 만약 경로보다 짧은 경로가 있고, 경로의 번째 미방문 꼭짓점을 라고 한다면 처음의 가정인 의해서 모순이 생긴다. 이와 비슷하게, 가는 경로 미방문 꼭짓점을 지나지 않는 짧은 경로가 있고, 경로의 마지막 꼭짓점이 라고 한다면, 이여야 하기 때문에 여전히 모순이 생긴다. 처리하고 나서도 각각의 미방문 꼭짓점 대해서, 여전히 방문한 꼭짓점만을 통해서 에서 로까지의 최단 거리이다. 이유는 통과하지 않는 경로 짧은 경로가 있다고 한다면 이미 찾았었을 것이며, 통하는 경로가 짧다면 처리할 갱신되었을 것이기 때문이다. == 실행 시간 == 간선 꼭짓점를 가지는 그래프에서 데이크스트라 알고리즘의 실행 시간의 상한은 대문자 표기법을 사용해서 변의 개수 꼭짓점의 개수 함수로 나타낼 있다. 상한을 어떻게 정하는지는 꼭짓점 집합 수행하는 방법에 의존한다. 다음에서, 어떤 그래프든지 이기 때문에 상한을 단순화 있지만, 단순화는 대한 다른 상한이 있을 있다는 점을 간과한다. 꼭짓점 집합 어떤 수행에서든지 수행 시간은 다음에 포함되어있다: 각각에서 연산의 복잡성이다. 가장 간단한 데이크스트라 알고리즘은 꼭짓점 집합 일반적인 연결 리스트나 배열로 저장하고, 단순히 있는 모든 꼭짓점의 선형 탐색이다. 따라서 경우에 실행 시간은 이다. 변이 보다 한참 적은 희소 그래프에 대해서는, 데이크스트라 알고리즘은 그래프를 인접 리스트의 형태로 저장하고 최소 추출을 효율적으로 하기 위해서 우선순위 큐로 자가 균형 이진 탐색 트리, 이진 힙, 페어링 힙, 또는 피보나치 힙을 사용해서 효율적으로 수행할 있다. decrease-key 단계를 이진 힙으로 효율적으로 수행하기 위해서는 각각의 꼭짓점에서 힙의 위치로 연결하는 보조 자료 구조를 사용하고 우선순위 바뀔 때마다 갱신할 필요가 있다. 자가 균형 이진 탐색 트리나 이진 힙에서 데이크스트라 알고리즘은 최악의 경우에 다음의 시간이 필요하다(는 이진 로그 의미한다): 연결 그래프에서는 시간 상한을 단순화 있다. 피보나치 힙은 시간을 다음과 같이 개선시킬 있다: :. 이진 힙을 사용할 때, 평균 시간복잡도는 최악의 경우 보다 낮다: 변의 비용이 일반적인 확률 분포와 무관하다고 가정하면, 연산의 기대 연산 횟수의 상한은 이므로, 수행 시간은 다음과 같아진다: :. 게다가, 그래프에 있는 모든 꼭짓점을 삽입하지 않으면 알고리즘을 무한 그래프나 메모리로 표현하기에는 너무 그래프에서 시작점에서 도착점까지의 최단 경로를 찾도록 확장할 있다. 결과로 나타나는 알고리즘은 인공지능 분야에서 ''균일 비용 탐색'' (UCS)이라고 불리고 다음의 의사 코드로 나타낼 있다 '''procedure''' start, goal) node start cost frontier priority queue containing node only explored empty set '''do''' '''if''' frontier is empty '''return''' failure node frontier.pop() '''if''' node is goal '''return''' solution '''for each''' of node's neighbors '''if''' is not in explored frontier.add(n) explored.add(n) 알고리즘의 복잡성은 매우 그래프에서 다른 방법으로 표현할 있다: 시작점에서 "도착" 예측을 만족하는 어떤 점으로 가는 최단 경로의 길이라고 하고, 각각의 변이 적어도 비용이 들며, 꼭짓점의 인접 꼭짓점의 개수가 최대 라고 한다면, 알고리즘의 최악의 경우와 공간복잡도는 이다. 단일 도착점의 경우의 데이크스트라 알고리즘을 최적화 것에는 양방향 변형이 있고, A* 알고리즘 같은 목적 지향 변형이 있으며( 참고), 어떤 꼭짓점이 최단 경로의 일부를 이룰 같은지를 결정하기 위한 그래프 가지치기가 있으며 (도달 기반 라우팅), 각각 "고속도로"를 이용한 전이 꼭짓점 간의 최단 경로 계산에 의한 "전이 꼭짓점"으로 연결시키기 위해서 라우팅을 감소시키는 입력된 그래프의 계급 분해를 사용할 있다. 이러 기술을 결합하는 것은 특정 문제에서 실제 최적의 수행에 필요할 있다. === 세분화된 변형 === 변의 비용이 작은 정수일 때(''C'' 보다 작을 때), 데이크스트라 알고리즘의 속도를 높이기 위해서 단조 우선순위 큐를 있다. 종류의 번째 알고리즘은 '''Dial's algorithm'''으로, 버켓 큐를 사용해서 수행 시간이 로, 정수 가중치를 갖는 그래프의 가중 지름에 의존한다. 판엠더 보아스 트리를 우선순위 큐로 사용하면 복잡성은 된다. 새로운 기수 힙과 알려진 피보나치 힙의 결합에 기반한 수행은 시간이 소요된다. 마지막으로, 여기에서 언급한 특수한 경우에 대한 최적의 알고리즘은 다음과 같다. 알고리즘은 시간이 소요되고 알고리즘은 시간이 소요된다. 또한 유향 비순환 그래프에서는 꼭짓점의 위상적 순서를 처리하고 각각의 꼭짓점까지의 길이를 들어오는 변을 통한 경로 최소 거리로 설정하면 주어진 시작점에서 선형 시간 만에 최단 경로를 찾을 있다. 가중치가 정수인 무향 연결 그래프의 경우의 데이크스트라 알고리즘은 의해 완전히 선형 복잡도 가진다. == 관련 문제와 알고리즘 == 데이크스트라의 알고리즘의 기능성은 변형의 다양성을 통해 확장할 있다. 예를 들면, 종종 수학적으로 최적인 해법을 나타내는 것이 바람직할 때가 있다. 최적 이하의 해법의 순위표를 얻기 위해서는 먼저 최적 해법을 계산해야 한다. 최적 해법의 변을 그래프에서 제거하고, 새로운 그래프에서 최적 해법을 계산한다. 원래 해법의 각각의 변을 차례로 제거하고 새로운 최단 경로를 계산한다. 그러면 번째 해법을 순위매기고 번째 최적 해법의 다음에 표시한다. 데이크스트라 알고리즘은 종종 링크 상태 라우팅 프로토콜의 원리에 의해 작동하며, OSPF와 IS-IS가 그중 가장 일반적인 것이다. 데이크스트라 알고리즘과는 달리, 벨먼-포드 알고리즘은 소스 꼭짓점 ''s''에서 도달할 있는 음수 사이클이 없으면 음수 가중치가 있을 때에도 사용할 있다. 이런 사이클이 존재하면, 사이클에 들어가서 바퀴를 때마다 전체 비용이 감소하기 때문에 최단 경로가 없다. 데이크스트라 알고리즘에 (음수 변을 제거하고 음수 사이클을 감지하기 위해)벨먼-포드 알고리즘을 결합해서 음수 가중치를 다룰 있으며, 이런 알고리즘은 존슨 알고리즘이라고 불린다. A* 알고리즘은 데이크스트라 알고리즘을 일반화 것으로, 목적지까지의 "거리"의 하한에 관한 정보를 얻을 있을 탐색해야 부분 그래프의 크기를 줄일 있다. 접근은 선형 계획법의 관점에서 있다: 최단 경로의 계산에서 선형 계획법이 있고, 쌍대 선형 계획법의 해법이 실행 가능하다는 것은 일관 휴리스틱을 형성한다는 것이다(대략적으로 말하면, 서명 관례가 문헌마다 다르기 때문이다). 실행 가능한 쌍대 일관 휴리스틱은 음이 아닌 감소 비용을 정의하고 A*은 본질적으로 감소 비용을 가지고 데이크스트라 알고리즘을 돌리는 것이다. 쌍대 선형 계획법이 약한 허용성 조건을 만족하면, A*는 벨먼-포드 알고리즘에 비슷하다. 데이크스트라 알고리즘의 기초가 되는 과정은 프림 알고리즘에서 사용되는 탐욕 과정과 유사하다. 프림 알고리즘의 목적은 그래프에 있는 모든 꼭짓점을 연결하는 최소 신장 트리를 찾는 것이나, 데이크스트라 알고리즘은 꼭짓점 만을 고려하는 것이다. 프림 알고리즘은 시작 꼭짓점의 전체 가중치로 평가하지 않고 각각의 가중치만을 평가한다. 너비 우선 탐색은 데이크스트라 알고리즘을 비가중 그래프에서, 우선순위 큐를 선입선출(FIFO) 큐로 만든 특수한 경우로 있다. 빠른 행진 방법은 삼각형 메쉬의 지오데식 거리를 계산하는 데이크스트라 알고리즘의 연속적인 버전으로 있다. === 동적 계획법의 관점 === 동적 계획법의 관점에서 보면, 데이크스트라 알고리즘은 '''도달''' 방법에서 생겨난 최단 경로 문제에 대한 동적 계획법 함수적 방정식을 푸는 연속적 근사 계획법이다. 사실, 알고리즘의 바탕이 되는 논리에 대한 데이크스트라의 설명 벨먼의 유명한 최적성의 원리를 최단 경로 문제의 맥락에서 해석한 것이다. == 같이 보기 == A* 알고리즘 벨먼-포드 알고리즘 유클리드 최단 경로 플러드 플로이드-워셜 알고리즘 존슨 알고리즘 최장 경로 문제 == 참조 == == 참고 문헌 == == 외부 링크 == Oral history interview with Edsger W. Dijkstra, Charles Babbage Institute University of Minnesota, Minneapolis. Implementation of Dijkstra's algorithm using TDD, Robert Cecil Martin, The Clean Code Blog Graphical explanation of Dijkstra's algorithm step-by-step on an example Gilles Bertrand, step by step graphical explanation of Dijkstra's algorithm operations 데이크스트라 알고리즘의 애니메이션 Boost 그래프 라이브러리(BGL) 인터랙티브 수행 분류:그래프 알고리즘 분류:검색 알고리즘 분류:라우팅 알고리즘 분류:조합 최적화 분류:의사코드가 있는 문서 분류:에츠허르 데이크스트라 분류:1959년 컴퓨팅