Dijkstra算法 python編程

Dijkstra算法(迪科斯徹算法、迪傑斯特拉算法):

迪傑斯特拉算法是由荷蘭計算機科學家狄克斯特拉於1959 年提出的,因此又叫狄克斯特拉算法。是從一個頂點到其餘各頂點的最短路徑算法,解決的是有向圖中最短路徑問題。迪傑斯特拉算法主要特點是以起始點爲中心向外層層擴展,直到擴展到終點爲止。

提出者:

         艾茲格·W·迪科斯徹 (Edsger Wybe Dijkstra,1930年5月11日~2002年8月6日)荷蘭人。 計算機科學家,畢業就職於荷蘭Leiden大學,早年鑽研物理及數學,而後轉爲計算學。曾在1972年獲得過素有計算機科學界的諾貝爾獎之稱的圖靈獎,之後,他還獲得過1974年 AFIPS Harry Goode Memorial Award、1989年ACM SIGCSE計算機科學教育教學傑出貢獻獎、以及2002年ACM PODC最具影響力論文獎。

Dijkstra算法python實現:

import heapq
import sys

class Graph:
	def __init__(self):
		self.vertices = {}
		
	def add_vertex(self, name, edges):
		self.vertices[name] = edges
	
	def get_shortest_path(self, startpoint, endpoint):
		#distances使用字典的方式保存每一個頂點到startpoint點的距離
		distances = {}
		
		#從startpoint到某點的最優路徑的前一個結點
		#eg:startpoint->B->D->E,則previous[E]=D,previous[D]=B,等等
		previous = {}
		
		#用來保存圖中所有頂點的到startpoint點的距離的優先隊列
		#這個距離不一定是最短距離
		nodes = []
		
		#Dikstra算法 數據初始化
		for vertex in self.vertices:
			if vertex == startpoint:
				#將startpoint點的距離初始化爲0
				distances[vertex] = 0
				heapq.heappush(nodes, [0, vertex])
			elif vertex in self.vertices[startpoint]:
				#把與startpoint點相連的結點距離startpoint點的距離初始化爲對應的弧長/路權
				distances[vertex] = self.vertices[startpoint][vertex]
				heapq.heappush(nodes, [self.vertices[startpoint][vertex], vertex])
				previous[vertex] = startpoint
			else:
				#把與startpoint點不直接連接的結點距離startpoint的距離初始化爲sys.maxsize
				distances[vertex] = sys.maxsize
				heapq.heappush(nodes, [sys.maxsize, vertex])
				previous[vertex] = None
		
		while nodes:
			#取出隊列中最小距離的結點
			smallest = heapq.heappop(nodes)[1]
			if smallest == endpoint:
				shortest_path = []
				lenPath = distances[smallest]
				temp = smallest
				while temp != startpoint:
					shortest_path.append(temp)
					temp = previous[temp]
				#將startpoint點也加入到shortest_path中
				shortest_path.append(temp)
			if distances[smallest] == sys.maxsize:
				#所有點不可達
				break
			#遍歷與smallest相連的結點,更新其與結點的距離、前繼節點
			for neighbor in self.vertices[smallest]:
				dis = distances[smallest] + self.vertices[smallest][neighbor]
				if dis < distances[neighbor]:
					distances[neighbor] = dis
					#更新與smallest相連的結點的前繼節點
					previous[neighbor] = smallest
					for node in nodes:
						if node[1] == neighbor:
							#更新與smallest相連的結點到startpoint的距離
							node[0] = dis
							break
					heapq.heapify(nodes)
		return shortest_path, lenPath
if __name__ == '__main__':
	g = Graph()
	g.add_vertex('a', {'b':6, 'd':2, 'f':5})
	g.add_vertex('b', {'a':6, 'c':4, 'd':5})
	g.add_vertex('c', {'b':4, 'e':4, 'h':6})
	g.add_vertex('d', {'a':2, 'b':5, 'e':6, 'f':4})
	g.add_vertex('e', {'d':6, 'c':4, 'g':5, 'h':4})
	g.add_vertex('f', {'a':5, 'd':4, 'g':9})
	g.add_vertex('g', {'f':9, 'e':5, 'h':5})
	g.add_vertex('h', {'c':6, 'e':4, 'g':5})
	start = 'a'
	end = 'e'
	shortestPath, len = g.get_shortest_path(start, end)
	print('{}->{}的最短路徑是:{},最短路徑爲:{}'.format(start, end, shortestPath, len))

最後的測試用例使用的是無向圖:

 

代碼如有誤,歡迎評論指出

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章