-
■ 다익스트라 알고리즘
1) 정의 :
자료구조로 graph 사용,
" 노드 + 가중치를 가진 간선 "을 이용하여 최단경로를 계산
2) graph 자료구조 참조
참조 : korshika.tistory.com/42?category=957674
3) 시간복잡도 :
O( E * log(E) ) ≒ O( E * log( V) )
> "최대의 경우"
모든 간선 E에 대해서 dist_history= [ ]가 한번씩 계산이 되기 때문에
간선을 queue에 작업하는 평균 시간 복잡도 O( log(E) )를 곱하면
최대 O( E * log(E) ) 에 비례,
> 일반적으로 노드는 간선보다 적기 때문에,
O( E * log( V) ) 라고 쓸 수도 있다
■ 코드 구현
1) 코드 이해코드 설명 참조 : Link
2) 코드 - 파이썬
import heapq # 복잡도 N log(N) /* # 유향 그래프 graph = { 'A': {'B': 8, 'C': 1, 'D': 2}, 'B': {}, 'C': {'B': 5, 'D': 2}, 'D': {'E': 3, 'F': 5}, 'E': {'F': 1}, 'F': {'A': 5} } */ def dijkstra(graph, start): q = [] recordDist = {node: float('inf') for node in graph} recordDist[start] = 0 # 시작 위치 0 distance heapq.heappush(q, [recordDist[start], start]) while q : curNodeDist, curNodeName = heapq.heappop(q) # 현재에서 가장 비용 낮은 순 탐색 """ 지금 방문한 node가 queue에 담긴 시점은 recordDist가 [section-b]에서 업데이트 되기 전일 수 있음 따라서 [section-a]에서 체크해줌 """ # [section-a] if recordDist[curNodeName] < curNodeDist: # 여기서 연결된 노드는 더 이상 볼필요가 없음, 이미 갱신되어서 # 옛날에 queue에 담긴 탐색 결과가 더 비용이 많이 들기 때문 continue # [section-b] for new_dest, new_dist in graph[curNodeName].items(): total_dist = curNodeDist + new_dist if total_dist < recordDist[new_dest]: recordDist[new_dest] = total_dist heapq.heappush(q, [total_dist, new_dest]) return recordDist
3) 예제
> 밑에 예제에서 확인가능 하지만, 유향 그래프로 설정하여도 되고 안해도 됨
> nested dictionary 사용
# 유향 그래프 graph = { 'A': {'B': 8, 'C': 1, 'D': 2}, 'B': {}, 'C': {'B': 5, 'D': 2}, 'D': {'E': 3, 'F': 5}, 'E': {'F': 1}, 'F': {'A': 5} } import heapq # 우선순위 큐 구현을 위함 def dijkstra(graph, start): distances = {node: float('inf') for node in graph} # start로 부터의 거리 값을 저장하기 위함 distances[start] = 0 # 시작 값은 0이어야 함 queue = [] heapq.heappush(queue, [distances[start], start]) # 시작 노드부터 탐색 시작 하기 위함. while queue: # queue에 남아 있는 노드가 없으면 끝 print(f'graph : {graph}') print(f'distances : {distances}') print(f'before queue : {queue}') current_distance, current_destination = heapq.heappop(queue) # 탐색 할 노드, 거리를 가져옴. print(f'current_distance : {current_distance}, current_destination : {current_destination}') print(f'distances[current_destination] : {distances[current_destination]}, current_distance : {current_distance}') if distances[current_destination] < current_distance: # 기존에 있는 거리보다 길다면, 볼 필요도 없음 continue for new_destination, new_distance in graph[current_destination].items(): distance = current_distance + new_distance # 해당 노드를 거쳐 갈 때 거리 if distance < distances[new_destination]: # 알고 있는 거리 보다 작으면 갱신 print(f'renew {new_destination} from {distances[new_destination]} to {distance}') distances[new_destination] = distance heapq.heappush(queue, [distance, new_destination]) # 다음 인접 거리를 계산 하기 위해 큐에 삽입 print(f'next queue : {queue}') print('\n'*2) return distances print(dijkstra(graph, 'A')) >>> graph : {'A': {'B': 8, 'C': 1, 'D': 2}, 'B': {}, 'C': {'B': 5, 'D': 2}, 'D': {'E': 3, 'F': 5}, 'E': {'F': 1}, 'F': {'A': 5}} distances : {'A': 0, 'B': inf, 'C': inf, 'D': inf, 'E': inf, 'F': inf} before queue : [[0, 'A']] current_distance : 0, current_destination : A distances[current_destination] : 0, current_distance : 0 renew B from inf to 8 renew C from inf to 1 renew D from inf to 2 next queue : [[1, 'C'], [8, 'B'], [2, 'D']] graph : {'A': {'B': 8, 'C': 1, 'D': 2}, 'B': {}, 'C': {'B': 5, 'D': 2}, 'D': {'E': 3, 'F': 5}, 'E': {'F': 1}, 'F': {'A': 5}} distances : {'A': 0, 'B': 8, 'C': 1, 'D': 2, 'E': inf, 'F': inf} before queue : [[1, 'C'], [8, 'B'], [2, 'D']] current_distance : 1, current_destination : C distances[current_destination] : 1, current_distance : 1 renew B from 8 to 6 next queue : [[2, 'D'], [8, 'B'], [6, 'B']] graph : {'A': {'B': 8, 'C': 1, 'D': 2}, 'B': {}, 'C': {'B': 5, 'D': 2}, 'D': {'E': 3, 'F': 5}, 'E': {'F': 1}, 'F': {'A': 5}} distances : {'A': 0, 'B': 6, 'C': 1, 'D': 2, 'E': inf, 'F': inf} before queue : [[2, 'D'], [8, 'B'], [6, 'B']] current_distance : 2, current_destination : D distances[current_destination] : 2, current_distance : 2 renew E from inf to 5 renew F from inf to 7 next queue : [[5, 'E'], [7, 'F'], [6, 'B'], [8, 'B']] graph : {'A': {'B': 8, 'C': 1, 'D': 2}, 'B': {}, 'C': {'B': 5, 'D': 2}, 'D': {'E': 3, 'F': 5}, 'E': {'F': 1}, 'F': {'A': 5}} distances : {'A': 0, 'B': 6, 'C': 1, 'D': 2, 'E': 5, 'F': 7} before queue : [[5, 'E'], [7, 'F'], [6, 'B'], [8, 'B']] current_distance : 5, current_destination : E distances[current_destination] : 5, current_distance : 5 renew F from 7 to 6 next queue : [[6, 'B'], [6, 'F'], [8, 'B'], [7, 'F']] graph : {'A': {'B': 8, 'C': 1, 'D': 2}, 'B': {}, 'C': {'B': 5, 'D': 2}, 'D': {'E': 3, 'F': 5}, 'E': {'F': 1}, 'F': {'A': 5}} distances : {'A': 0, 'B': 6, 'C': 1, 'D': 2, 'E': 5, 'F': 6} before queue : [[6, 'B'], [6, 'F'], [8, 'B'], [7, 'F']] current_distance : 6, current_destination : B distances[current_destination] : 6, current_distance : 6 next queue : [[6, 'F'], [7, 'F'], [8, 'B']] graph : {'A': {'B': 8, 'C': 1, 'D': 2}, 'B': {}, 'C': {'B': 5, 'D': 2}, 'D': {'E': 3, 'F': 5}, 'E': {'F': 1}, 'F': {'A': 5}} distances : {'A': 0, 'B': 6, 'C': 1, 'D': 2, 'E': 5, 'F': 6} before queue : [[6, 'F'], [7, 'F'], [8, 'B']] current_distance : 6, current_destination : F distances[current_destination] : 6, current_distance : 6 next queue : [[7, 'F'], [8, 'B']] graph : {'A': {'B': 8, 'C': 1, 'D': 2}, 'B': {}, 'C': {'B': 5, 'D': 2}, 'D': {'E': 3, 'F': 5}, 'E': {'F': 1}, 'F': {'A': 5}} distances : {'A': 0, 'B': 6, 'C': 1, 'D': 2, 'E': 5, 'F': 6} before queue : [[7, 'F'], [8, 'B']] current_distance : 7, current_destination : F distances[current_destination] : 6, current_distance : 7 graph : {'A': {'B': 8, 'C': 1, 'D': 2}, 'B': {}, 'C': {'B': 5, 'D': 2}, 'D': {'E': 3, 'F': 5}, 'E': {'F': 1}, 'F': {'A': 5}} distances : {'A': 0, 'B': 6, 'C': 1, 'D': 2, 'E': 5, 'F': 6} before queue : [[8, 'B']] current_distance : 8, current_destination : B distances[current_destination] : 6, current_distance : 8 {'A': 0, 'B': 6, 'C': 1, 'D': 2, 'E': 5, 'F': 6}
참조:
[알고리즘] Dijikstra 최단경로 알고리즘
다익스트라 알고리즘의 pseudo-code와 C 코드는 위키피디아에 잘 나와 있으므로 그곳을 참고한다. 이 글은 어떻게 그 알고리즘을 생각하게 되었을까 를 내 나름대로 생각해 본 후 그에 대하여 쓴
gyrfalcon.tistory.com
www.fun-coding.org/Chapter20-shortest-live.html
파이썬과 컴퓨터 사이언스(고급 알고리즘): 최단 경로 알고리즘의 이해 - 잔재미코딩
2단계: 우선순위 큐에서 추출한 (A, 0) [노드, 첫 노드와의 거리] 를 기반으로 인접한 노드와의 거리 계산¶ 우선순위 큐에서 노드를 꺼냄 처음에는 첫 정점만 저장되어 있으므로, 첫 정점이 꺼내짐
www.fun-coding.org
justkode.kr/algorithm/python-dijkstra
Python으로 다익스트라(dijkstra) 알고리즘 구현하기
최단 경로 알고리즘은 지하철 노선도, 네비게이션 등 다방면에 사용되는 알고리즘입니다. 이번 시간에는 Python을 이용해 하나의 시작 정점으로 부터 모든 다른 정점까지의 최단 경로를 찾는 최
justkode.kr
smlee729.github.io/python/network%20analysis/2015/04/12/1-dijkstra.html
Dijkstra 알고리즘을 이용한 Minimum Cost Search | Jacob's Coding Playground
이번에 살펴볼 알고리즘은 아주 아주 많이 사용되고 또 중요한 Dijkstra 알고리즘에 대해서 알아보겠습니다. 특히나 graph theory에서는 안쓰이는 곳이 없을 정도로 많이 사용되니 반드시 잘 숙지하
smlee729.github.io
반응형'알고리즘 > 탐색' 카테고리의 다른 글
플로이드와샬 / 플로이드 - 와샬 (0) 2021.05.11 크루스칼 (0) 2021.05.10 이진 탐색 ( Binary Search ) (0) 2021.05.02 BFS / DFS (0) 2021.03.25 graph(map) 구현(python) (0) 2021.03.25