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))

最后的测试用例使用的是无向图:

 

代码如有误,欢迎评论指出

Dijkstra算法是一种用于解决单源最短路径问题的贪心算法,主要基于图的数据结构。它的基本思想是通过不断地扩展当前已经找到的最短路径来找到从源节点到其他所有节点的最短路径。 具体的实现过程可以分为以下几个步骤: 1. 创建一个集合用于存储已经找到最短路径的节点,将源节点添加到集合中,并将源节点的距离设置为0。 2. 创建一个优先队列用于存储未找到最短路径的节点,将所有节点添加到队列中,并将它们的距离设置为正无穷。 3. 从队列中取出距离源节点最近的节点,并将其加入到已找到最短路径的集合中。 4. 遍历当前节点的所有邻居节点,如果当前节点到邻居节点的距离加上当前节点到源节点的距离小于邻居节点的距离,则更新邻居节点的距离。 5. 重复第3步和第4步,直到队列为空或者找到了目标节点。 下面是一个简单的Python实现: ```python import heapq def dijkstra(graph, start): distances = {node: float('inf') for node in graph} distances[start] = 0 queue = [(0, start)] while queue: current_distance, current_node = heapq.heappop(queue) if distances[current_node] < current_distance: continue for neighbor, weight in graph[current_node].items(): distance = current_distance + weight if distance < distances[neighbor]: distances[neighbor] = distance heapq.heappush(queue, (distance, neighbor)) return distances ``` 其中,`graph`是一个字典类型的变量,用于存储图的邻接表表示方式,`start`是源节点的标识符。函数返回一个字典类型的变量,存储了源节点到其他所有节点的最短距离。 在代码中,我们使用了`heapq`模块来实现优先队列,这样可以保证每次取出的节点都是距离源节点最近的节点。同时,我们使用一个`distances`字典来记录每个节点到源节点的距离,初始值为正无穷。在遍历图的过程中,如果发现新的距离比已有距离更小,就更新距离,并将邻居节点加入到队列中等待处理。 这就是Dijkstra算法Python编程思想。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值