【学习 记录】狄克斯特拉算法 - Java
最近学习《算法图解》一书时,看到狄克斯特拉算法之前没有使用过,在学习后用常用语言Java将算法实现出来以加深印象。
作用
狄克斯特拉算法用于找出最快的路径,而常用的广度优先搜索算法可用于找出最短的路径。
限制
狄克斯特拉算法作用于:单向、加权图且无负权边
算法步骤
- 在未处理的节点中找出开销最小的节点
- 遍历开销最小节点的邻居(邻边)
- 如果经当前节点前往该邻居更近,则更新到达该邻居的开销
- 同时将该邻居的父节点设置为当前节点
- 遍历完当前节点的邻边后,将当前节点标记为已处理
- 找出下一个开销最小且未处理过的节点,循环上面的步骤
目标图
算法步骤
1. 将图转换成数据结构
这里将图转换成Map
/*** 将图转化成Map** @return*/
private static Map<String, Map<String, Integer>> initGraphMap() {Map<String, Integer> startPoint = new HashMap<>();startPoint.put("A", 6);startPoint.put("B", 2);Map<String, Integer> aPoint = new HashMap<>();aPoint.put("final", 1);Map<String, Integer> bPoint = new HashMap<>();bPoint.put("A", 3);bPoint.put("final", 5);Map<String, Map<String, Integer>> graphMap = new HashMap<>();graphMap.put("start", startPoint);graphMap.put("A", aPoint);graphMap.put("B", bPoint);graphMap.put("final", new HashMap<>());return graphMap;
}
转换后的关系图如下:
2. 初始化记录达到每个节点的花销数据结构
因为我们肯定是从起点开始,所以需要先将起点能够达到的所有邻边的花销记录起来
private static void initMap(String startPoint) {// 通过起点找关联的邻边Map<String, Integer> pointMap = GRAPH_MAP.get(startPoint);// 如果起点没有邻边,就直接返回结束if (pointMap == null) {return;}// 一开始起点能到达的地方,且需要花费的金钱,就等于costsMap的初始化MapCOSTS_MAP = pointMap;// 需要给costsMap加上达到终点的花费,默认为Integer.MAX_VALUECOSTS_MAP.put("final", Integer.MAX_VALUE);// 初始化parentsMap,维护好起点和邻边的关系for (Map.Entry<String, Integer> pointEntry : pointMap.entrySet()) {// 起点能达到的地方String point = pointEntry.getKey();PARENTS_MAP.put(point, "start");}
}
初始化后的开销图如下:
初始化后的父节点关系图如下:
3. 找出开销最小且未处理过的节点
private static String findLowestCostPoint() {Integer minCost = Integer.MAX_VALUE;String targetPoint = null;// 遍历costsMap,找出花费最小的节点for (Map.Entry<String, Integer> costEntry : COSTS_MAP.entrySet()) {String point = costEntry.getKey();Integer cost = costEntry.getValue();if (cost < minCost && !HISTORY_SET.contains(point)) {minCost = cost;targetPoint = point;}}return targetPoint;
}
4. 遍历开销最小节点的邻边,如果经当前节点前往邻边更近,则更新到达该邻边的开销,并且维护父节点的关系
public static void main(String[] args) {if (COSTS_MAP == null) {System.out.println("地图为空!");return;}String lowestCostPoint = findLowestCostPoint();while (lowestCostPoint != null) {// 首先拿到到达给当前最小花费节点所需费用Integer cost = COSTS_MAP.get(lowestCostPoint);// 获取到最小花费节点所能到达的节点列表Map<String, Integer> targetPointMap = GRAPH_MAP.get(lowestCostPoint);// 遍历最小花费节点所能到达的节点,并计算所需花费for (Map.Entry<String, Integer> targetEntry : targetPointMap.entrySet()) {String currentPoint = targetEntry.getKey();// 到达当前节点所需费用Integer newCost = targetEntry.getValue() + cost;// 判断当前所能到达的节点,是否已经存在costsMap当中if (COSTS_MAP.containsKey(currentPoint)) {// 如果存在,则判断不同路径到达该节点的费用哪个更便宜if (newCost < COSTS_MAP.get(currentPoint)) {// 如果新的路径更便宜,则更新costsMap以及parentsMapCOSTS_MAP.put(currentPoint, newCost);PARENTS_MAP.put(currentPoint, lowestCostPoint);}continue;}// 如果不存在,则直接更新costsMap以及parentsMapCOSTS_MAP.put(currentPoint, newCost);PARENTS_MAP.put(currentPoint, lowestCostPoint);}// 将当前节点从添加到已处理列表中HISTORY_SET.add(lowestCostPoint);// 再次寻找花费最小的节点lowestCostPoint = findLowestCostPoint();}
}
开销图的执行经过,绿色背景表示已经处理过,下次不可再处理的节点:
父节点关系维护图的执行经过,通过这个关系图,我们可以还原整个最快路径:
Show me the code
public class Dijkstra {// GRAPH,将图转换成Mapprivate static Map<String, Map<String, Integer>> GRAPH_MAP;// COSTS,记录到达每个节点的花费private static Map<String, Integer> COSTS_MAP;// PARENTS,记录父节点路径private static Map<String, String> PARENTS_MAP = new HashMap<>();// 记录已经处理过的节点private static Set<String> HISTORY_SET = new HashSet<>();public static void main(String[] args) {// 将图初始化成MapGRAPH_MAP = initGraphMap();// 根据graphMap,计算出初始化的花费和父节点MapinitMap("start");if (COSTS_MAP == null) {System.out.println("地图为空!");return;}String lowestCostPoint = findLowestCostPoint();while (lowestCostPoint != null) {// 首先拿到到达给当前最小花费节点所需费用Integer cost = COSTS_MAP.get(lowestCostPoint);// 获取到最小花费节点所能到达的节点列表Map<String, Integer> targetPointMap = GRAPH_MAP.get(lowestCostPoint);// 遍历最小花费节点所能到达的节点,并计算所需花费for (Map.Entry<String, Integer> targetEntry : targetPointMap.entrySet()) {String currentPoint = targetEntry.getKey();// 到达当前节点所需费用Integer newCost = targetEntry.getValue() + cost;// 判断当前所能到达的节点,是否已经存在costsMap当中if (COSTS_MAP.containsKey(currentPoint)) {// 如果存在,则判断不同路径到达该节点的费用哪个更便宜if (newCost < COSTS_MAP.get(currentPoint)) {// 如果新的路径更便宜,则更新costsMap以及parentsMapCOSTS_MAP.put(currentPoint, newCost);PARENTS_MAP.put(currentPoint, lowestCostPoint);}continue;}// 如果不存在,则直接更新costsMap以及parentsMapCOSTS_MAP.put(currentPoint, newCost);PARENTS_MAP.put(currentPoint, lowestCostPoint);}// 将当前节点从添加到已处理列表中HISTORY_SET.add(lowestCostPoint);// 再次寻找花费最小的节点lowestCostPoint = findLowestCostPoint();}// 得到最短路径List<String> path = getPath();System.out.println("最短路径为:" + path.toString());}private static List<String> getPath() {List<String> path = new LinkedList<>();String parent = PARENTS_MAP.get("final");path.add(0, "final");while (parent != null) {path.add(0, parent);parent = PARENTS_MAP.get(parent);}return path;}private static String findLowestCostPoint() {Integer minCost = Integer.MAX_VALUE;String targetPoint = null;// 遍历costsMap,找出花费最小的节点for (Map.Entry<String, Integer> costEntry : COSTS_MAP.entrySet()) {String point = costEntry.getKey();Integer cost = costEntry.getValue();if (cost < minCost && !HISTORY_SET.contains(point)) {minCost = cost;targetPoint = point;}}return targetPoint;}private static void initMap(String startPoint) {Map<String, Integer> pointMap = GRAPH_MAP.get(startPoint);if (pointMap == null) {return;}// 一开始起点能到达的地方,且需要花费的金钱,就等于costsMap的初始化MapCOSTS_MAP = pointMap;// 需要给costsMap加上达到终点的花费,默认为Integer.MAX_VALUECOSTS_MAP.put("final", Integer.MAX_VALUE);// 初始化parentsMapfor (Map.Entry<String, Integer> pointEntry : pointMap.entrySet()) {// 起点能达到的地方String point = pointEntry.getKey();PARENTS_MAP.put(point, "start");}}/*** 将图转化成Map** @return*/private static Map<String, Map<String, Integer>> initGraphMap() {Map<String, Integer> startPoint = new HashMap<>();startPoint.put("A", 6);startPoint.put("B", 2);Map<String, Integer> aPoint = new HashMap<>();aPoint.put("final", 1);Map<String, Integer> bPoint = new HashMap<>();bPoint.put("A", 3);bPoint.put("final", 5);Map<String, Map<String, Integer>> graphMap = new HashMap<>();graphMap.put("start", startPoint);graphMap.put("A", aPoint);graphMap.put("B", bPoint);graphMap.put("final", new HashMap<>());return graphMap;}
}
结尾
算法的实现以及圈复杂度都存在优化的空间,后续想优化的时候再优化~
【学习 记录】狄克斯特拉算法 - Java相关推荐
- 算法学习之狄克斯特拉算法
加权图 在了解狄克斯特拉算法之前,先介绍一下加权图. 如图,假设你要从起点出发到达终点,如果只考虑换乘少,即最短路径.那么可以使用广度优先搜索算法,该算法我之前简单的写过,链接点这里.但是,现在你要找 ...
- 《算法图解》学习笔记(七):狄克斯特拉算法(附代码)
欢迎关注WX公众号:[程序员管小亮] python学习之路 - 从入门到精通到大师 文章目录 欢迎关注WX公众号:[程序员管小亮] [python学习之路 - 从入门到精通到大师](https://b ...
- 图解算法学习笔记(七):狄克斯特拉算法
目录 1)使用狄克斯特拉算法 2)术语 3)实现 4)小结 本章内容; 介绍加权图,提高或降低某些边的权重: 介绍狄克斯特拉算法,找出加权图中前往X的最短路径: 介绍图中的环,它导致狄克斯特拉算法不管 ...
- 狄克斯特拉算法 - 学习整理
个人整理,原创发布,转载请标注博客来源.https://editor.csdn.net/md/?articleId=102799813 很多时候,总会忽略了一些你认为不需要的知识体系,但最终你发现,你 ...
- 初学狄克斯特拉算法~(待提高)
读书笔记 狄克斯特拉算用来寻找加权图的"最短路径"(不一定是段数最少,我们需要一定的量度,比如说最少花费,最短时间等,bfs只是解决了段数的最短路径问题) 鉴于无向图就是一个环,而 ...
- 算法图解part7:狄克斯特拉算法
算法图解part7:狄克斯特拉(Dijkstra)算法 1.狄克斯特拉算法(Dijkstra's algorithm) 2.术语 3.负权边 4.实现狄克斯特拉算法 4.1 最短路径思路 4.2 py ...
- 迪杰斯特拉算法c++_《算法图解》学习记录7--迪杰斯特拉算法
本章内容 继续图的讨论,介绍加权图--提高或降低某些边的权重. 介绍狄克斯特拉dijstra算法,让你能够找出加权图中前往X的最短路径. 介绍图中的环,它导致狄克斯特拉算法不管用. 在前一 ...
- 小白的算法初识课堂(part7)--狄克斯特拉算法
学习笔记 学习书目:<算法图解>- Aditya Bhargava 文章目录 狄克斯特拉算法 具体步骤实现 术语 跳蚤市场 具体步骤实现 负权边 python实现 狄克斯特拉算法 在上一个 ...
- 算法(四):图解狄克斯特拉算法
算法简介 狄克斯特拉算法(Dijkstra )用于计算出不存在非负权重的情况下,起点到各个节点的最短距离 可用于解决2类问题: 从A出发是否存在到达B的路径: 从A出发到达B的最短路径(时间最少.或者 ...
最新文章
- 你见过最差的算法工程师什么样?
- Spring Boot定时任务应用实践
- QML自定义图表图例
- 如何配置html prettify,[HTML] Prettify 代码高亮使用总结
- Web前端开发笔记——第二章 HTML语言 第四节 超链接标签
- web应用程序并发测试_测试并发应用
- java 格式化时间计算
- mysql union 不同字段_mysql中union和union all的区别和注意点
- python基础教程廖雪峰云-为什么看不懂廖雪峰的Python学习教程?
- spf13-vim安装与使用
- Python基于wordnet实现词语相似度计算分析
- “会用LabVIEW,但是却没有听说TestStand,好像有点说不过去吧!”(下)
- informix数据库维护常用命令
- (附源码)计算机毕业设计SSM教务排课管理系统
- INTELLIJ IDEA 2017 破解教程(2018也可以!)
- 更有效的编写QQ空间、CSDN、博客园图文并茂的文章
- ElasticSearch安装IK分词器并使用IK分词器和Kibana进行自定义词汇
- matplotlib plot画图不弹框
- 一文读懂BLOB算法
- 部分HTTPS网站无法访问的可能原因
热门文章
- uniapp 电商app 下载页面功能实现
- 自建工单(审批流)系统设计
- 明星热图|王嘉尔、刘诗诗代言新品牌;王一博、周笔畅、刘恺威出席活动;吴彦祖、黄晓明演绎品牌大片...
- 香港中文大学助理教授周博磊:十年之间的CVPR与我们
- 2021 回头看看这一年
- 虚拟机安装与配置<3>---VMware 16.0上调整虚拟电脑的配置
- jy-11-AJAX--承租红+成恒
- 生产者剩余的几何解释
- 【CYH-02】NOIp考砸后虐题赛:转换式:题解
- 信息[http-nio-80-exec-9] org. apache. coyote. http11. Httpl1Processor.service解析注意:HTTP请求解析错误的进--步发生将记录