針對
無權圖
能夠使用深度優先和廣度優先算法,有權圖
能夠使用最短路徑算法
node
Dijkstra(迪傑斯特拉算法): 在有向加權圖
中查找最短路徑python
注意: 該算法只適用於有向無環圖
, 不適用於負權邊的狀況算法
思路:數據結構
下表爲要從起點到達終點, 數字爲花費的時間app
父節點 | 節點 | 花費 |
---|---|---|
start | A | 6 |
start | B | 2 |
B | A | 5 |
B | end | 7 |
A | end | 6 |
上圖是按照以上步驟進行填充的數據結構和算法
start
的鄰居節點A
和B
, 其中B
的花費最少B
節點的鄰居節點A
和end
, 更新到A節點
的開銷A節點
進行, 從A
到end
花費最小, 更新B
到end
的開銷因此最小距離爲start --> B --> A --> end
code
利用最小堆實現, 時間複雜度: O(e * logv), e是邊的個數blog
# -*- coding:utf-8 -*- ''' Dijkstra算法(最短路徑算法) - 適用於有向有權無環圖 - 不適用於負權邊的狀況 ''' import heapq class Graph(object): def __init__(self): self.graph = {} def add_edge(self, start: str, end: str, distance: float): self.graph.setdefault(start, {}) self.graph[start][end] = distance def dijkstra(start: str, end: str, graph: dict) -> list: visited = set() # 存儲已經處理過的節點 costs = {start: 0} queue = [(0, start)] path = {} # 用於復原路徑 while queue: dis, min_node = heapq.heappop(queue) if min_node == end: break if min_node not in visited: visited.add(min_node) neighbors = graph[min_node] for i, j in neighbors.items(): new_dis = dis + j if (i not in costs) or (new_dis < costs[i]): costs[i] = new_dis heapq.heappush(queue, (new_dis, i)) path[i] = min_node res = [] key = end while key != start: res.append(key) key = path[key] res.append(start) res.reverse() return res if __name__ == '__main__': g1 = Graph() g1.add_edge('start', 'a', 3) g1.add_edge('start', 'b', 2) g1.add_edge('b', 'a', 6) g1.add_edge('b', 'end', 5) g1.add_edge('a', 'end', 1) assert dijkstra('start', 'end', g1.graph) == ['start', 'a', 'end'] g2 = Graph() g2.add_edge('start', 'a', 5) g2.add_edge('start', 'b', 2) g2.add_edge('b', 'a', 1) g2.add_edge('b', 'end', 5) g2.add_edge('a', 'end', 1) assert dijkstra('start', 'end', g2.graph) == ['start', 'b', 'a', 'end']