最短路径(Dijkstra算法),一文必看懂最短路径的方法

最短路径问题(Dijkstra算法)

从图中的某一个顶点出发到达另一个顶点的所经过的边的权重和最小的一条路径,称为最短路径。
Dijkstra算法适用于求一个节点到其他节点的最短路径,主要特点是通过广度搜索(由近及远、层层扩展)来遍历其他所有需要求距离的点的思想来解决最短路径问题。

在这里插入图片描述

一个辅助数组D,记录从起始节点到当前节点的最短距离。一个辅助数组V,观察这个节点是否最终被确定下来
第一轮的迭代:一开始的起始节点是A,A到A的距离为0。然后看A附近的邻居节点(B,C,D)的距离(A到B,C,D最短路径长度)。E道不了所以是正无穷。此时V(A)为1。即起始节点到A的最短路径已经被确认下来了。
在这里插入图片描述
第二次迭代:从还没有确定下来的节点中(V=0),**选出A节点到这些未确定下来的节点中的最小的距离的节点。**这时候是C节点,把C节点的标记数组V(C)=1。然后根据C节点的邻居节点,来更新C节点到这些邻居节点(B和E,A已经被标记过了所以不算)的最短路径。这时更新B节点发现,A到B的最短路径是10,A到C到B的最短路径为3 + 2 = 5,所以会取它的最小值5作为A到B的最短路径。E节点同理,最短路径为18。
在这里插入图片描述
第三次迭代:在未确定节点中B,D,E中的最小值,此时是B节点,V(B)=1。从A到B到到D的路径大小是5 + 5 =10,从A到D的路径为20,所以我们选择10作为最短路径。E不是B的邻居节点所以不更新。

第四次迭代,找的是D节点。V(D)=1。D到E的距离为21,所以不更新。

最后得到的最后结果就是,从节点A到各个节点的最短距离了。
在这里插入图片描述
如果想知道路径是多少,就在加入一个辅助数组P。P来记录每个节点的上一个节点到这个节点的最短路径的节点编号。

步骤概括:
1.第一个核心步骤:找到当前未处理过的顶点中Distance最小的点V,(由于起点到起点的消耗为0,所以算法开始时V必定代表起点)
2.第二个核心步骤:若V有邻居,则计算经过V的情况下起点到达各邻居的消耗Distance,并选择是否更新V邻居的Distance值。若没有邻居则对该点的处理结束。(也称为松弛操作)
3.重复以上两个核心步骤,直到满足算法终止的条件:有向图所有的点都被处理过。

时间复杂度:
设有向图中,共有V个顶点,E条边。
传统Dijkstra算法中主要操作有:
1.每次从确定节点中寻找Distance最小节点,需要O((V-1)+…+2+1)=O(V ^ 2)
2.更新邻居的Distance,需要O(E)
所以总的时间复杂度为O(V ^ 2 +E),E当V无限大的时候可以省略,所以时间复杂度为O(V ^ 2)。

题目(Leetcode 743):
有N个网络节点,标记为1到N。给定一个列表times,表示信号经过有向边的传递时间。times[i] = (u,v,w),其中u是源节点,v是目标节点,w是一个信号从源节点传递到目标节点的时间。
现在,我们向当前的节点k发送了一个信号。需要多久才能使所有节点都收到信号?如果不能使所有节点收到信号,返回-1。

这是一个单圆最短路径问题,找到最远的那个节点的最短路径所花费的时间,就能找到使所有的节点都收到信号的时间。因为最远的那个节点收到信号,代表所有的节点都能收到信号。

class Solution:
	def networkDelayTime(self,times,N,K):
		# N+1是为了把0这个索引忽略掉,让D数组和网络节点对齐
		# 除起始节点外,所有节点初始化为正无穷
		D = [float('inf')] * (N+1)
		# graph这个字典,键存储的是源节点,值里面存储的是源节点所能到的目标节点和时间
		graph = {}
		for u,v,w in times:
			# dict.get 是找到键为u中的值,没有的话就为[]
			graph[u] = graph.get(u,[]) + [(v,w)]
		# 判断从起始节点到该节点的最短路径是否已经确认
		visited = [0] * (N + 1)
		# 起始节点初始化为0
		D[k] = 0
		# 除起始节点外,还需要确定N-1个起始节点到每一个节点的最短路径
		for i in range(N - 1):
			minDistance = float('inf')
			minIndex = 1
			# 找到未确定最短路径节点集合中的距离最小值
			for j in range(1,N+1):
				if not visited[j] and D[j] < minDistance:
					minDistance = D[j]
					minIndex = j
			visited[minIndex] = 1
			# 更新这个minIndex节点能到达的邻居上面的最短路径
			if minIndex in graph.keys():
				for v,w in graph[minIndex]:
					if not visited[v]:
						D[v] = min(D[minIndex] + w,D[v])
						# 在这里可以记录路径 :
						#if D[V] = D[minIndex] + w:
							#p[v] = minIindex
		maxDistance = -1
		for i in range(1,N+1):
			if D[i] == float('inf'):
				return -1
			maxDistance = max(maxDistance,D[i])
		return maxDistance 
				
  • 16
    点赞
  • 74
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值