이 기사에서는 가장 일반적으로 알려진 최단 경로 알고리즘 중 하나인 네덜란드 컴퓨터 과학자 Edsger W. Dijkstra가 1956년에 개발한 Dijkstra의 최단 경로 알고리즘에 대해 설명합니다. 또한 이 알고리즘에 대한 복잡성 분석을 수행하고 다른 최단 경로 알고리즘과 어떻게 다른지 확인하세요.
내용의 테이블
- Dijkstra의 알고리즘
- Dijkstra 알고리즘의 필요성(목적 및 활용 사례)
- Dijkstra의 알고리즘은 방향성 그래프와 무방향성 그래프 모두에서 작동할 수 있습니까?
- Dijkstra 알고리즘에 대한 알고리즘
- Dijkstra의 알고리즘은 어떻게 작동합니까?
- Dijkstra 알고리즘의 의사 코드
- Dijkstra 알고리즘의 구현:
- Dijkstra 알고리즘과 Bellman-Ford 알고리즘 비교
- Dijkstra 알고리즘과 Floyd-Warshall 알고리즘
- Dijkstra 알고리즘과 A* 알고리즘 비교
- Dijkstra 알고리즘의 연습 문제
- 결론:

Dijkstra의 알고리즘:
Dijkstra의 알고리즘 그래프에서 음수가 아닌 간선 가중치를 갖는 많은 단일 소스 최단 경로 문제를 해결하기 위해 널리 사용되는 알고리즘입니다. 즉, 그래프에서 두 정점 사이의 최단 거리를 찾는 것입니다. 네덜란드의 컴퓨터 과학자가 고안한 것입니다. 에드저 W. 데이크스트라 1956년에.
알고리즘은 방문한 정점 집합과 방문하지 않은 정점 집합을 유지합니다. 소스 정점에서 시작하여 소스로부터 임시 거리가 가장 작은 방문하지 않은 정점을 반복적으로 선택합니다. 그런 다음 이 정점의 이웃을 방문하고 더 짧은 경로가 발견되면 임시 거리를 업데이트합니다. 이 프로세스는 대상 정점에 도달하거나 도달 가능한 모든 정점을 방문할 때까지 계속됩니다.
Dijkstra 알고리즘의 필요성(목적 및 활용 사례)
Dijkstra 알고리즘의 필요성은 두 지점 사이의 최단 경로를 찾는 것이 중요한 많은 응용 분야에서 발생합니다.
예를 들어 , 컴퓨터 네트워크의 라우팅 프로토콜에 사용될 수 있으며 지도 시스템에서 출발지와 목적지 사이의 최단 경로를 찾는 데에도 사용할 수 있습니다(19페이지에서 설명). Google 지도는 어떻게 작동하나요? )
Dijkstra의 알고리즘은 방향성 그래프와 무방향성 그래프 모두에서 작동할 수 있습니까?
예 , Dijkstra의 알고리즘은 음수가 아닌 간선 가중치를 갖고 연결되어야 하는 요구 사항을 충족하는 한 모든 유형의 그래프에서 작동하도록 설계되었으므로 유향 그래프와 무향 그래프 모두에서 작동할 수 있습니다.
- 방향성 그래프에서, 각 가장자리에는 가장자리로 연결된 정점 사이의 이동 방향을 나타내는 방향이 있습니다. 이 경우 알고리즘은 최단 경로를 검색할 때 가장자리의 방향을 따릅니다.
- 무방향 그래프에서, 가장자리에는 방향이 없으며 알고리즘은 최단 경로를 검색할 때 가장자리를 따라 앞뒤로 이동할 수 있습니다.
Dijkstra 알고리즘에 대한 알고리즘:
- 소스 노드를 현재 거리가 0으로 표시되고 나머지는 무한대로 표시됩니다.
- 현재 거리가 가장 작은 방문하지 않은 노드를 현재 노드로 설정합니다.
- 각 이웃에 대해 현재 노드의 N은 인접 노드의 현재 거리에 0->1을 연결하는 간선의 가중치를 더합니다. 현재 Node의 거리보다 작다면 새로운 현재 거리 N으로 설정합니다.
- 현재 노드 1을 방문한 것으로 표시합니다.
- 방문하지 않은 노드가 있으면 2단계로 이동합니다.
Dijkstra의 알고리즘은 어떻게 작동합니까?
아래 예제를 통해 Dijkstra 알고리즘이 어떻게 작동하는지 살펴보겠습니다.
Dijkstra의 알고리즘은 그래프의 노드 0에서 다른 모든 노드까지의 최단 경로를 생성합니다.
아래 그래프를 고려하십시오.
Dijkstra의 알고리즘
알고리즘은 그래프의 노드 0에서 다른 모든 노드까지의 최단 경로를 생성합니다.
이 그래프에서는 간선의 가중치가 두 노드 사이의 거리를 나타낸다고 가정합니다.
김프 JPEG로 저장보시다시피, 우리는 다음에서 가장 짧은 경로를 가지고 있습니다.
노드 0에서 노드 1까지,
노드 0부터 노드 2까지,
노드 0부터 노드 3까지,
노드 0부터 노드 4까지,
노드 0~노드 6.처음에는 아래와 같은 리소스 세트가 있습니다.
- 소스 노드에서 자체 노드까지의 거리는 0입니다. 이 예에서 소스 노드는 0입니다.
- 소스 노드에서 다른 모든 노드까지의 거리는 알 수 없으므로 모두 무한대로 표시합니다.
예: 0 -> 0, 1-> ,2-> 지, 3-> 지, 4-> 지, 5-> 지, 6-> 지.
- 또한 방문하지 않았거나 표시되지 않은 노드를 추적하는 방문하지 않은 요소 배열도 갖게 됩니다.
- 방문한 것으로 표시된 모든 노드와 노드 사이의 거리가 경로에 추가되면 알고리즘이 완료됩니다. 방문하지 않은 노드:- 0 1 2 3 4 5 6.
1 단계: Node 0에서 시작하여 Node를 방문한 것으로 표시합니다. 아래 이미지에서 확인할 수 있듯이 방문한 Node는 빨간색으로 표시됩니다.
Dijkstra의 알고리즘
2 단계: 인접한 노드를 확인합니다. 이제 선택해야 합니다(거리 2의 노드 1을 선택하거나 거리 6의 노드 2 선택). 최소 거리의 노드를 선택합니다. 이 단계에서는 노드 1 노드에 인접한 최소 거리이므로 방문한 것으로 표시하고 거리를 합산합니다.
테스트 mockito 준비거리: 노드 0 -> 노드 1 = 2
Dijkstra의 알고리즘
3단계: 그런 다음 앞으로 이동하여 노드 3인 인접한 노드를 확인하여 방문한 것으로 표시하고 거리를 합산하면 이제 거리는 다음과 같습니다.
거리: 노드 0 -> 노드 1 -> 노드 3 = 2 + 5 = 7
Dijkstra의 알고리즘
4단계: 다시 한번 인접 노드에 대해 두 가지 선택 사항이 있으므로(거리가 10인 노드 4를 선택하거나 거리가 15인 노드 5를 선택할 수 있음) 최소 거리가 있는 노드를 선택합니다. 이 단계에서는 노드 4 노드에 인접한 최소 거리이므로 방문한 것으로 표시하고 거리를 합산합니다.
거리: 노드 0 -> 노드 1 -> 노드 3 -> 노드 4 = 2 + 5 + 10 = 17
Dijkstra의 알고리즘
5단계: 다시 앞으로 이동하여 인접한 노드를 확인합니다. 노드 6 , 방문한 것으로 표시하고 거리를 합산하면 이제 거리는 다음과 같습니다.
거리: 노드 0 -> 노드 1 -> 노드 3 -> 노드 4 -> 노드 6 = 2 + 5 + 10 + 2 = 19
Dijkstra의 알고리즘
따라서 Source Vertex로부터의 최단 거리는 19이며 이는 최적의 거리입니다.
Dijkstra 알고리즘의 의사 코드
함수 Dijkstra(그래프, 소스):
// 모든 노드까지의 거리를 무한대로 초기화하고 소스 노드까지의 거리를 0으로 초기화합니다.거리 = 지도(모든 노드 -> 무한대)
거리 = 0
// 방문할 노드를 추적하기 위해 빈 방문 노드 세트와 우선순위 대기열을 초기화합니다.
방문 = 빈 세트
대기열 = 새로운 PriorityQueue()
queue.enqueue(소스, 0)// 모든 노드를 방문할 때까지 반복합니다.
대기열이 비어 있지 않은 동안:
// 우선순위 큐로부터 거리가 가장 짧은 노드를 큐에서 제거합니다.
현재 = queue.dequeue()// 이미 방문한 노드라면 건너뜁니다.
현재 방문한 경우:
계속하다// 노드를 방문한 것으로 표시합니다.
방문.추가(현재)// 모든 이웃 노드를 검사하여 거리를 업데이트해야 하는지 확인합니다.
Graph.neighbors(current)의 이웃에 대해:
// 현재 노드를 통해 이웃까지의 임시 거리를 계산합니다.
tentative_distance = 거리[현재] + Graph.distance(현재, 이웃)// 임시 거리가 이웃까지의 현재 거리보다 작으면 거리를 업데이트합니다.
임시_거리인 경우
거리[이웃] = 임시_거리// 향후 방문을 위해 고려할 새로운 거리로 이웃을 대기열에 넣습니다.
queue.enqueue(이웃, 거리[이웃])피트 데이비슨 나이// 소스에서 그래프의 다른 모든 노드까지 계산된 거리를 반환합니다.
왕복 거리
Dijkstra 알고리즘의 구현:
Dijkstra의 알고리즘을 구현하는 방법에는 여러 가지가 있지만 가장 일반적인 방법은 다음과 같습니다.
- 우선순위 대기열(힙 기반 구현):
- 어레이 기반 구현:
1. Priority_queue(힙)을 사용한 Dijkstra의 최단 경로 알고리즘
이 구현에서는 그래프와 그래프의 소스 정점이 제공되어 소스에서 주어진 그래프의 모든 정점까지의 최단 경로를 찾습니다.
예:
입력: 소스 = 0
예
산출: 꼭지점
소스로부터의 정점 거리
0 -> 0
1 -> 2
2 -> 6
3 -> 7
4 -> 17
5 -> 22
6 -> 19
위의 아이디어를 기반으로 한 알고리즘은 다음과 같습니다.
- 거리 값과 우선순위 대기열을 초기화합니다.
- 거리가 0인 우선순위 큐에 소스 노드를 삽입합니다.
- 우선순위 큐가 비어 있지 않은 동안:
- 우선순위 큐로부터 최소 거리를 가진 노드를 추출합니다.
- 더 짧은 경로가 발견되면 이웃의 거리를 업데이트합니다.
- 업데이트된 이웃을 우선순위 대기열에 삽입합니다.
다음은 위 접근 방식의 C++ 구현입니다.
C++ // Program to find Dijkstra's shortest path using // priority_queue in STL #include using namespace std; #define INF 0x3f3f3f3f // iPair ==>정수 쌍 typedef 쌍 아이페어; // 이 클래스는 // 인접 목록 표현을 사용하여 유향 그래프를 나타냅니다. class Graph { int V; // 정점 수 // 가중치 그래프에서는 // 모든 간선 목록에 대해 정점과 가중치 쌍을 저장해야 합니다.>* 조정; 공개: 그래프(int V); // 생성자 // 그래프에 간선을 추가하는 함수 void addEdge(int u, int v, int w); // s에서 최단 경로를 인쇄합니다. void shortestPath(int s); }; // 인접 목록에 대한 메모리 할당 Graph::Graph(int V) { this->V = V; adj = 새 목록 [V]; } void Graph::addEdge(int u, int v, int w) { adj[u].push_back(make_pair(v, w)); adj[v].push_back(make_pair(u, w)); } // src에서 다른 모든 정점까지의 최단 경로를 인쇄합니다. void Graph::shortestPath(int src) { // 전처리 중인 정점을 저장하기 위해 // 우선순위 대기열을 생성합니다. 이것은 C++의 이상한 구문입니다. // 이 구문에 대한 자세한 내용은 아래 링크를 참조하세요. // https://www.techcodeview.com Priority_queue , 보다 큰 > pq; // 거리에 대한 벡터를 생성하고 // 모든 거리를 무한(INF) 벡터로 초기화합니다. dist(V,INF); // 소스 자체를 우선순위 큐에 삽입하고 // 거리를 0으로 초기화합니다. pq.push(make_pair(0, src)); 거리[src] = 0; /* 우선순위 큐가 비워질 때까지(또는 모든 거리가 확정되지 않을 때까지 반복) */ while (!pq.empty()) { // 쌍의 첫 번째 정점은 최소 거리입니다. // 정점, 우선순위 큐에서 추출합니다. // 정점 레이블은 쌍의 두 번째 항목에 저장됩니다(정점을 유지하려면 // 이 방법을 사용해야 합니다. // 정렬된 거리(거리는 // 쌍의 첫 번째 항목이어야 합니다) int u = pq.top().second; pq.pop(); // 'i'는 정점 목록의 모든 인접 정점을 가져오는 데 사용됩니다.>::반복자 i; for (i = adj[u].begin(); i != adj[u].end(); ++i) { // 정점 레이블과 현재 // u에 인접한 가중치를 가져옵니다. int v = (*i).first; int 가중치 = (*i).second; // u를 통해 v로의 단축 경로가 있는 경우. if (dist[v]> dist[u] + Weight) { // v의 거리 업데이트 dist[v] = dist[u] + Weight; pq.push(make_pair(dist[v], v)); } } } // dist[]에 저장된 최단 거리를 인쇄합니다. printf('소스로부터의 정점 거리
'); for (int i = 0; i< V; ++i) printf('%d %d
', i, dist[i]); } // Driver program to test methods of graph class int main() { // create the graph given in above figure int V = 7; Graph g(V); // making above shown graph g.addEdge(0, 1, 2); g.addEdge(0, 2, 6); g.addEdge(1, 3, 5); g.addEdge(2, 3, 8); g.addEdge(3, 4, 10); g.addEdge(3, 5, 15); g.addEdge(4, 6, 2); g.addEdge(5, 6, 6); g.shortestPath(0); return 0; }>
자바 import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.PriorityQueue; public class DijkstraAlgoForShortestDistance { static class Node implements Comparable{ int v; 정수 거리; 공개 노드(int v, int distance) { this.v = v; this.distance = 거리; } @Override public int CompareTo(Node n) { if (this.distance<= n.distance) { return -1; } else { return 1; } } } static int[] dijkstra( int V, ArrayList >> adj, int S) { boolean[] 방문 = new boolean[V]; 해시맵 map = 새로운 HashMap(); 우선순위 대기열q = 새로운 우선순위큐(); map.put(S, new Node(S, 0)); q.add(새 노드(S, 0)); while (!q.isEmpty()) { 노드 n = q.poll(); int v = n.v; int 거리 = n.거리; 방문[v] = true; 배열목록 > adjList = adj.get(v); for(ArrayList adjLink : adjList) { if (visited[adjLink.get(0)] == false) { if (!map.containsKey(adjLink.get(0))) { map.put( adjLink.get(0), new Node (v, 거리 + adjLink.get(1))); } else { 노드 sn = map.get(adjLink.get(0)); if (거리 + adjLink.get(1)< sn.distance) { sn.v = v; sn.distance = distance + adjLink.get(1); } } q.add(new Node(adjLink.get(0), distance + adjLink.get(1))); } } } int[] result = new int[V]; for (int i = 0; i < V; i++) { result[i] = map.get(i).distance; } return result; } public static void main(String[] args) { ArrayList >> 조정 = 새로운 ArrayList(); 해시맵 >> 지도 = 새로운 HashMap(); 정수 V = 6; 정수 E = 5; int[] u = { 0, 0, 1, 2, 4 }; int[] v = { 3, 5, 4, 5, 5 }; int[] w = { 9, 4, 4, 10, 3 }; for (int i = 0; i< E; i++) { ArrayList 가장자리 = 새로운 ArrayList(); edge.add(v[i]); edge.add(w[i]); 배열목록 > 조정목록; if (!map.containsKey(u[i])) { adjList = new ArrayList(); } else { adjList = map.get(u[i]); } adjList.add(가장자리); map.put(u[i], adjList); 배열목록 edge2 = 새로운 ArrayList(); edge2.add(u[i]); edge2.add(w[i]); 배열목록 > 조정목록2; if (!map.containsKey(v[i])) { adjList2 = new ArrayList(); } else { adjList2 = map.get(v[i]); } adjList2.add(edge2); map.put(v[i], adjList2); } for (int i = 0; i< V; i++) { if (map.containsKey(i)) { adj.add(map.get(i)); } else { adj.add(null); } } int S = 1; // Input sample //[0 [[3, 9], [5, 4]], // 1 [[4, 4]], // 2 [[5, 10]], // 3 [[0, 9]], // 4 [[1, 4], [5, 3]], // 5 [[0, 4], [2, 10], [4, 3]] //] int[] result = DijkstraAlgoForShortestDistance.dijkstra( V, adj, S); System.out.println(Arrays.toString(result)); } }> 파이썬 # Python implementation of Dijkstra Algorithm import heapq class Node: def __init__(self, v, distance): self.v = v self.distance = distance def __lt__(self, other): return self.distance < other.distance def dijkstra(V, adj, S): visited = [False] * V map = {} q = [] map[S] = Node(S, 0) heapq.heappush(q, Node(S, 0)) while q: n = heapq.heappop(q) v = n.v distance = n.distance visited[v] = True adjList = adj[v] for adjLink in adjList: if not visited[adjLink[0]]: if adjLink[0] not in map: map[adjLink[0]] = Node(v, distance + adjLink[1]) else: sn = map[adjLink[0]] if distance + adjLink[1] < sn.distance: sn.v = v sn.distance = distance + adjLink[1] heapq.heappush(q, Node(adjLink[0], distance + adjLink[1])) result = [0] * V for i in range(V): result[i] = map[i].distance return result def main(): adj = [[] for _ in range(6)] V = 6 E = 5 u = [0, 0, 1, 2, 4] v = [3, 5, 4, 5, 5] w = [9, 4, 4, 10, 3] for i in range(E): edge = [v[i], w[i]] adj[u[i]].append(edge) edge2 = [u[i], w[i]] adj[v[i]].append(edge2) S = 1 result = dijkstra(V, adj, S) print(result) if __name__ == '__main__': main() # This code is contributed by ragul21> 씨# // C# Code: using System; using System.Collections.Generic; public class Graph { // No. of vertices private int V; // adjacency list private List>[] 조정; // 생성자 public Graph(int v) { V = v; adj = 새 목록>[ v ]; for (int i = 0; i< v; ++i) adj[i] = new List>(); } // 그래프에 간선을 추가하는 함수 public void addEdge(int u, int v, int w) { adj[u].Add(Tuple.Create(v, w)); adj[v].Add(Tuple.Create(u, w)); } // s에서 최단 경로를 인쇄합니다. public void shortestPath(int s) { // 전처리 중인 정점을 저장하기 위해 // 우선순위 대기열을 만듭니다. var pq = 새로운 PriorityQueue>(); // 거리에 대한 벡터를 생성하고 // 모든 거리를 무한(INF)으로 초기화합니다. var dist = new int[V]; for (int i = 0; i< V; i++) dist[i] = int.MaxValue; // Insert source itself in priority queue and // initialize its distance as 0. pq.Enqueue(Tuple.Create(0, s)); dist[s] = 0; /* Looping till priority queue becomes empty (or all distances are not finalized) */ while (pq.Count != 0) { // The first vertex in pair is the minimum // distance vertex, extract it from priority // queue. vertex label is stored in second of // pair (it has to be done this way to keep the // vertices sorted distance (distance must be // first item in pair) var u = pq.Dequeue().Item2; // 'i' is used to get all adjacent vertices of a // vertex foreach(var i in adj[u]) { // Get vertex label and weight of current // adjacent of u. int v = i.Item1; int weight = i.Item2; // If there is shorted path to v through u. if (dist[v]>dist[u] + Weight) { // v의 거리 업데이트 dist[v] = dist[u] + Weight; pq.Enqueue(Tuple.Create(dist[v], v)); } } } // dist[]에 저장된 최단 거리를 인쇄합니다. Console.WriteLine('소스로부터의 정점 거리'); for (int i = 0; i< V; ++i) Console.WriteLine('{0} {1}', i, dist[i]); } } public class PriorityQueue{ 개인 읽기 전용 목록_데이터; 개인 읽기 전용 비교_비교; 공개 PriorityQueue(): this(비교.기본값) { } 공개 PriorityQueue(IComparer비교): this(비교.비교) { } 공개 PriorityQueue(비교비교) { _data = 새 목록(); _비교 = 비교; } public void Enqueue(T 항목) { _data.Add(item); var childIndex = _data.Count - 1; while (childIndex> 0) { var parentIndex = (childIndex - 1) / 2; if (_compare(_data[childIndex], _data[parentIndex])>= 0) break; T tmp = _data[childIndex]; _data[childIndex] = _data[parentIndex]; _data[parentIndex] = tmp; childIndex = 부모인덱스; } } public T Dequeue() { // pq가 비어 있지 않다고 가정합니다. 호출 코드까지 var lastElement = _data.Count - 1; var 앞항목 = _data[0]; _data[0] = _data[마지막요소]; _data.RemoveAt(lastElement); --lastElement; var parentIndex = 0; while (true) { var childIndex = parentIndex * 2 + 1; if (childIndex> lastElement) 브레이크; // 트리 끝 var rightChild = childIndex + 1; if(오른쪽자식<= lastElement && _compare(_data[rightChild], _data[childIndex]) < 0) childIndex = rightChild; if (_compare(_data[parentIndex], _data[childIndex]) <= 0) break; // Correct position T tmp = _data[parentIndex]; _data[parentIndex] = _data[childIndex]; _data[childIndex] = tmp; parentIndex = childIndex; } return frontItem; } public T Peek() { T frontItem = _data[0]; return frontItem; } public int Count { get { return _data.Count; } } } class Program { // Driver program to test methods of graph class static void Main(string[] args) { // create the graph given in above figure int V = 7; Graph g = new Graph(V); // making above shown graph g.addEdge(0, 1, 2); g.addEdge(0, 2, 6); g.addEdge(1, 3, 5); g.addEdge(2, 3, 8); g.addEdge(3, 4, 10); g.addEdge(3, 5, 15); g.addEdge(4, 6, 2); g.addEdge(5, 6, 6); g.shortestPath(0); } }> 자바스크립트 class PriorityQueue { constructor() { this.queue = []; } enqueue(element, priority) { this.queue.push({ element, priority }); this.queue.sort((a, b) =>a.우선순위 - b.우선순위); } dequeue() { if (this.isEmpty()) { return null; } return this.queue.shift().element; } isEmpty() { return this.queue.length === 0; } } 클래스 그래프 { 생성자(V) { this.V = V; this.adj = 새로운 배열(V); for (나는 = 0이라고 하자; 나는< V; i++) { this.adj[i] = []; } } addEdge(u, v, w) { this.adj[u].push({ v, w }); this.adj[v].push({ v: u, w }); } shortestPath(src) { const pq = new PriorityQueue(); const dist = new Array(this.V).fill(Infinity); const visited = new Array(this.V).fill(false); pq.enqueue(src, 0); dist[src] = 0; while (!pq.isEmpty()) { const u = pq.dequeue(); if (visited[u]) continue; visited[u] = true; for (const { v, w } of this.adj[u]) { if (!visited[v] && dist[u] + w < dist[v]) { dist[v] = dist[u] + w; pq.enqueue(v, dist[v]); } } } console.log('Vertex Distance from Source'); for (let i = 0; i < this.V; i++) { console.log(`${i} ${dist[i] === Infinity ? 'Infinity' : dist[i]}`); } } } function main() { const V = 7; const g = new Graph(V); g.addEdge(0, 1, 2); g.addEdge(0, 2, 6); g.addEdge(1, 3, 5); g.addEdge(2, 3, 8); g.addEdge(3, 4, 10); g.addEdge(3, 5, 15); g.addEdge(4, 6, 2); g.addEdge(5, 6, 6); g.shortestPath(0); } main();> 최종 답변:

산출
Dijkstra 알고리즘의 복잡성 분석 :
- 시간 복잡도: O((V + E) 로그 V) , 여기서 V는 정점 수이고 E는 가장자리 수입니다.
- 보조 공간: O(V), 여기서 V는 정점 수이고 E는 그래프의 간선 수입니다.
2.Dijkstra 알고리즘의 배열 기반 구현(순진한 접근 방식):
Dijkstra 알고리즘은 우선순위 큐를 사용하지 않고 배열을 사용하여 구현할 수도 있습니다. 이 구현은 간단하지만 특히 큰 그래프에서는 효율성이 떨어질 수 있습니다.
알고리즘은 다음과 같이 진행됩니다.
C에서 배열 길이를 얻으십시오
- 소스에서 각 노드까지의 거리를 저장하기 위해 배열을 초기화합니다.
- 모든 노드를 방문하지 않은 것으로 표시합니다.
- 소스 노드까지의 거리를 0으로 설정하고 다른 모든 노드에 대해서는 무한대로 설정합니다.
- 모든 노드를 방문할 때까지 반복합니다.
- 알려진 거리가 가장 작은 방문하지 않은 노드를 찾습니다.
- 현재 노드에 대해 방문하지 않은 이웃의 거리를 업데이트합니다.
- 현재 노드를 방문한 것으로 표시합니다.
복잡성 분석:
- 시간 복잡도: 최악의 경우 O(V^2), 여기서 V는 정점 수입니다. 이는 일부 최적화를 통해 O(V^2)로 개선될 수 있습니다.
- 보조 공간: O(V), 여기서 V는 정점 수이고 E는 그래프의 간선 수입니다.
Dijkstra 알고리즘과 Bellman-Ford 알고리즘 비교
Dijkstra의 알고리즘과 벨만-포드 알고리즘 둘 다 가중치 그래프에서 최단 경로를 찾는 데 사용되지만 몇 가지 중요한 차이점이 있습니다. Dijkstra 알고리즘과 Bellman-Ford 알고리즘의 주요 차이점은 다음과 같습니다.
| 특징: | 데이크스트라의 | 벨먼 포드 |
|---|---|---|
| 최적화 | 음수가 아닌 간선 가중치를 갖는 그래프에서 단일 소스 노드와 다른 모든 노드 사이의 최단 경로를 찾는 데 최적화되었습니다. | Bellman-Ford 알고리즘은 음의 간선 가중치를 갖는 그래프에서 단일 소스 노드와 다른 모든 노드 사이의 최단 경로를 찾는 데 최적화되어 있습니다. |
| 기분 전환 | Dijkstra의 알고리즘은 거리가 가장 작은 노드를 선택하고 이웃 노드를 업데이트하는 탐욕적 접근 방식을 사용합니다. | Bellman-Ford 알고리즘은 각 반복에서 모든 가장자리를 완화하여 해당 노드에 대한 모든 가능한 경로를 고려하여 각 노드의 거리를 업데이트합니다. |
| 시간 복잡도 | Dijkstra의 알고리즘은 조밀한 그래프의 경우 O(V^2), 희소 그래프의 경우 O(E log V)의 시간 복잡도를 갖습니다. 여기서 V는 정점 수이고 E는 그래프의 간선 수입니다. | Bellman-Ford 알고리즘은 O(VE)의 시간 복잡도를 가지며, 여기서 V는 정점 수이고 E는 그래프의 간선 수입니다. |
| 음수 가중치 | Dijkstra의 알고리즘은 모든 간선 가중치가 음수가 아니라고 가정하므로 음수 간선 가중치를 갖는 그래프에서는 작동하지 않습니다. | Bellman-Ford 알고리즘은 음의 간선 가중치를 처리할 수 있으며 그래프에서 음의 가중치 주기를 감지할 수 있습니다. |
Dijkstra 알고리즘과 Floyd-Warshall 알고리즘
Dijkstra의 알고리즘과 플로이드-워샬 알고리즘 둘 다 가중치 그래프에서 최단 경로를 찾는 데 사용되지만 몇 가지 중요한 차이점이 있습니다. Dijkstra 알고리즘과 Floyd-Warshall 알고리즘의 주요 차이점은 다음과 같습니다.
| 특징: | 데이크스트라의 | 플로이드-워샬 알고리즘 |
|---|---|---|
| 최적화 | 음수가 아닌 간선 가중치를 갖는 그래프에서 단일 소스 노드와 다른 모든 노드 사이의 최단 경로를 찾는 데 최적화되었습니다. | Floyd-Warshall 알고리즘은 그래프의 모든 노드 쌍 사이의 최단 경로를 찾는 데 최적화되어 있습니다. |
| 기술 | Dijkstra의 알고리즘은 그리디 접근법을 사용하고 소스 노드에서 그래프의 다른 모든 노드까지의 최단 경로를 계산하는 단일 소스 최단 경로 알고리즘입니다. | 반면에 Floyd-Warshall 알고리즘은 동적 프로그래밍을 사용하여 그래프의 모든 노드 쌍 사이의 최단 경로를 계산하는 모든 쌍 최단 경로 알고리즘입니다. |
| 시간 복잡도 | Dijkstra의 알고리즘은 조밀한 그래프의 경우 O(V^2), 희소 그래프의 경우 O(E log V)의 시간 복잡도를 갖습니다. 여기서 V는 정점 수이고 E는 그래프의 간선 수입니다. | 반면에 Floyd-Warshall 알고리즘은 동적 프로그래밍을 사용하여 그래프의 모든 노드 쌍 사이의 최단 경로를 계산하는 모든 쌍 최단 경로 알고리즘입니다. |
| 음수 가중치 | Dijkstra의 알고리즘은 모든 간선 가중치가 음수가 아니라고 가정하므로 음수 간선 가중치를 갖는 그래프에서는 작동하지 않습니다. | 반면에 Floyd-Warshall 알고리즘은 동적 프로그래밍을 사용하여 그래프의 모든 노드 쌍 사이의 최단 경로를 계산하는 모든 쌍 최단 경로 알고리즘입니다. |
Dijkstra 알고리즘과 A* 알고리즘 비교
Dijkstra의 알고리즘과 A* 알고리즘 둘 다 가중치 그래프에서 최단 경로를 찾는 데 사용되지만 몇 가지 중요한 차이점이 있습니다. Dijkstra 알고리즘과 A* 알고리즘의 주요 차이점은 다음과 같습니다.
| 특징: | A* 알고리즘 | |
|---|---|---|
| 검색 기술 | 음수가 아닌 간선 가중치를 갖는 그래프에서 단일 소스 노드와 다른 모든 노드 사이의 최단 경로를 찾는 데 최적화되었습니다. | A* 알고리즘은 휴리스틱 기능을 사용하여 목표 노드를 향해 검색을 안내하는 정보 검색 알고리즘입니다. |
| 휴리스틱 기능 | Dijkstra의 알고리즘은 휴리스틱 기능을 사용하지 않고 그래프의 모든 노드를 고려합니다. | A* 알고리즘은 현재 노드에서 목표 노드까지의 거리를 추정하는 휴리스틱 함수를 사용합니다. 이 휴리스틱 함수는 허용됩니다. 즉, 목표 노드까지의 실제 거리를 과대평가하지 않는다는 의미입니다. |
| 시간 복잡도 | Dijkstra의 알고리즘은 조밀한 그래프의 경우 O(V^2), 희소 그래프의 경우 O(E log V)의 시간 복잡도를 갖습니다. 여기서 V는 정점 수이고 E는 그래프의 간선 수입니다. | A* 알고리즘의 시간 복잡도는 휴리스틱 기능의 품질에 따라 달라집니다. |
| 애플리케이션 | Dijkstra의 알고리즘은 라우팅 알고리즘, GPS 내비게이션 시스템, 네트워크 분석 등 다양한 응용 분야에서 사용됩니다. | . A* 알고리즘은 비디오 게임, 로봇 공학 및 계획 알고리즘과 같은 경로 찾기 및 그래프 순회 문제에 일반적으로 사용됩니다. |
Dijkstra 알고리즘의 연습 문제:
- Dijkstra의 최단 경로 알고리즘 | 탐욕스러운 알고-7
- 인접 목록 표현을 위한 Dijkstra의 알고리즘 | 탐욕스러운 알고-8
- Dijkstra의 알고리즘 – 우선순위 대기열 및 배열 구현
- STL의 집합을 사용한 Dijkstra의 최단 경로 알고리즘
- C++에서 STL을 사용하는 Dijkstra의 최단 경로 알고리즘
- STL의 Priority_queue를 이용한 Dijkstra의 최단 경로 알고리즘
- C++에서 행렬을 사용하는 Dijkstra의 최단 경로 알고리즘
- DAG의 단일 소스 최단 경로에 대한 Dijkstra 알고리즘
- 피보나치 힙을 사용한 Dijkstra 알고리즘
- 음의 가중치를 갖는 유향 그래프에 대한 Dijkstra의 최단 경로 알고리즘
- Dijkstra의 최단 경로 알고리즘으로 경로 인쇄
- Java의 우선순위 큐를 사용하는 Dijkstra의 최단 경로 알고리즘




