图的Dijkstra算法(最短路径)

不要在意这张图的箭头。

把他当成一个无向图。

计算从v1开始到达每个点的最短路径

迪杰斯特拉原理:

首先v1到达v6 有两种方式。

直接到达。或者通过回路 到达

首先将v1 的直接后续节点找出来

v6,v5,v3

找到距离最短的那条边。

v1 到 v3 =10。

直接就可以确定,v1到v3的最短距离是10.

因为。v1 直接到达 v3 距离是10 。

通过回路到达。 势必经过 v5 和v3 。他们两条路本身就比v1-v3长。因此。通过回路肯定比直接到达距离要长。

 

确定 v1 到 v3 最短距离 是 10

看看v3 可以到达的点。

v2、v4

v1 通过 v3 到达 v2 的距离是 10+5 =15
v1 通过 v3 到达 v4 的距离是 10+50 =60
v1 直接到达 v6 的距离是 100
v1 直接到达 v5 的距离是  30

 

此时再次找出 距离最小的那个 路径。

 

v1 通过 v3 到达 v2 的距离是 10+5 =15

确定:v1 到达 v2 通过这样的方式是最短的

原因:

如果v1 不采用这条方案他就得采用

v1 通过 v3 到达 v4 的距离是 10+50 =60
v1 直接到达 v6 的距离是 100
v1 直接到达 v5 的距离是  30

 

这三条方案中的一个去到达 v2

这三条方案。再走其他的路。

距离肯定是大于 v1 通过 v3 到达 v2 的距离是 10+5 =15

v2 没有后续节点所以不需要更新。

 

此时有 剩下 3 条方案

 

v1 通过 v3 到达 v4 的距离是 10+50 =60
v1 直接到达 v6 的距离是 100
v1 直接到达 v5 的距离是  30

再次找到最小距离。

 

v1 直接到达 v5 的距离是  30


不写完了总结下吧。

解法:

 

使用一个集合放入。v1 的 所有 临界 边

找到最小的一条。 v1到 v3 最 短的距离

然后,更新。看看v1 到 v3 后还能到达那几个节点。 如果原来的集合中没有的话,就添加进集合

如果集合中有的话,比较下。

v1 通过 v3 到达这个点 的距离 是否 小于 他原来通过不知名方式到达这个点的距离。

是的话, 替代。

 

package basic_class_05;

import java.util.*;
import java.util.Map.Entry;

public class Dijksra {
	public static HashMap<Node, Integer> dijkstra1(Node head) {
		//key :意思是, 我的初始节点将要到达的节点。
		//value :我的初始节点将要到达的节点的距离。
		HashMap<Node,Integer> distanceMap = new HashMap<Node,Integer>();
		distanceMap.put(head,0);//自己到达自己的距离是0
		
		//这个用来存放已经找到的最短距离 --防止重复
		HashSet<Node> selectedNodes = new HashSet<Node>();
		
		Node minNode = getMinDistanceAndUnselectedNode(distanceMap,selectedNodes);
		while(minNode!=null){
			int distance = distanceMap.get(minNode);
			for(Edge edge:minNode.edges){
				Node toNode = edge.to;
				//集合中没有到这个点的距离的话,就插入。
				if(!distanceMap.containsKey(toNode)){
					distanceMap.put(toNode,distance+toNode.value);
				}
				//判断新增加的距离。 是否小于 以存在的距离
				distanceMap.put(edge.to, Math.min(distanceMap.get(toNode), distance + edge.weight));
			}
			//添加,已经确定的 最短距离。
			selectedNodes.add(minNode);
			minNode = getMinDistanceAndUnselectedNode(distanceMap, selectedNodes);
		}
		return distanceMap;
	}
	
	
	//这个函数找到 集合中,距离最小的
	//距离小,并且,没有在touchedNodes 集合中。
	public static Node getMinDistanceAndUnselectedNode(HashMap<Node, Integer> distanceMap,HashSet<Node> touchedNodes){
		Node minNode = null;
		int minDistance = Integer.MAX_VALUE;
		for(Node node:distanceMap.keySet() ){
			int value = distanceMap.get(node);
			if(value<minDistance&&!touchedNodes.contains(node)){
				minNode =node;
				minDistance = value;
			}
		}
		return minNode;
		
	} 
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Dijkstra算法是一种用于解决单源最路径问题的算法。它通过贪婪地选择当前最路径来逐步构建最路径树。以下是Dijkstra算法的步骤: 1. 创建一个空的最路径集合,用于存储从起始节点到其他节点的最路径。 2. 初始化起始节点的最路径为0,将其添加到最路径集合中。 3. 对于起始节点的所有邻居节点,更新它们的最路径值。如果通过当前节点到达邻居节点的路径比已知的最路径,则更新最路径值。 4. 从未添加到最路径集合中的节点中选择一个具有最小最路径值的节点,并将其添加到最路径集合中。 5. 重复步骤3和步骤4,直到所有节点都被添加到最路径集合中。 6. 最终,最路径集合中存储了从起始节点到所有其他节点的最路径Dijkstra算法的特点和限制如下: - Dijkstra算法仅适用于非负权重的,因为它依赖于贪婪策略来选择当前最路径。 - 它可以找到从起始节点到所有其他节点的最路径,因此适用于单源最路径问题。 - Dijkstra算法不会处理负权边,如果中存在负权边,应该使用其他算法,如Bellman-Ford算法。 - 算法的时间复杂度取决于数据结构的选择,一般情况下是O(V^2)或O(Vlog(V)),其中V是节点数。如果使用优先队列来优化,时间复杂度可以减小到O(Elog(V)),其中E是边数。 以下是一个使用Dijkstra算法找到最路径的示例代码: ```python import sys def dijkstra(graph, start): # 初始化最路径集合和最路径字典 shortest_paths = {node: sys.maxsize for node in graph} shortest_paths[start] = 0 visited = set() while len(visited) < len(graph): # 选择当前最路径值的节点 current_node = min((node for node in graph if node not in visited), key=lambda node: shortest_paths[node]) visited.add(current_node) # 更新邻居节点的最路径值 for neighbor in graph[current_node]: distance = shortest_paths[current_node] + graph[current_node][neighbor] if distance < shortest_paths[neighbor]: shortest_paths[neighbor] = distance return shortest_paths # 示例的邻接表表示 graph = { 'A': {'B': 5, 'C': 3}, 'B': {'A': 5, 'C': 1, 'D': 3}, 'C': {'A': 3, 'B': 1, 'D': 2, 'E': 6}, 'D': {'B': 3, 'C': 2, 'E': 4, 'F': 2}, 'E': {'C': 6, 'D': 4, 'F': 6}, 'F': {'D': 2, 'E': 6} } start_node = 'A' shortest_paths = dijkstra(graph, start_node) for node in shortest_paths: print(f"Shortest path from {start_node} to {node}: {shortest_paths[node]}") ``` 这段代码使用邻接表表示,并从起始节点'A'开始找到到达其他节点的最路径。最终,它会输出从起始节点到每个节点的最路径值。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SUNbrightness

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值