最近学习《算法图解》一书时,看到狄克斯特拉算法之前没有使用过,在学习后用常用语言Java将算法实现出来以加深印象。

作用

狄克斯特拉算法用于找出最快的路径,而常用的广度优先搜索算法可用于找出最短的路径

限制

狄克斯特拉算法作用于:单向、加权图且无负权边

算法步骤

  1. 在未处理的节点中找出开销最小的节点
  2. 遍历开销最小节点的邻居(邻边)
  3. 如果经当前节点前往该邻居更近,则更新到达该邻居的开销
  4. 同时将该邻居的父节点设置为当前节点
  5. 遍历完当前节点的邻边后,将当前节点标记为已处理
  6. 找出下一个开销最小且未处理过的节点,循环上面的步骤

目标图

算法步骤

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相关推荐

  1. 算法学习之狄克斯特拉算法

    加权图 在了解狄克斯特拉算法之前,先介绍一下加权图. 如图,假设你要从起点出发到达终点,如果只考虑换乘少,即最短路径.那么可以使用广度优先搜索算法,该算法我之前简单的写过,链接点这里.但是,现在你要找 ...

  2. 《算法图解》学习笔记(七):狄克斯特拉算法(附代码)

    欢迎关注WX公众号:[程序员管小亮] python学习之路 - 从入门到精通到大师 文章目录 欢迎关注WX公众号:[程序员管小亮] [python学习之路 - 从入门到精通到大师](https://b ...

  3. 图解算法学习笔记(七):狄克斯特拉算法

    目录 1)使用狄克斯特拉算法 2)术语 3)实现 4)小结 本章内容; 介绍加权图,提高或降低某些边的权重: 介绍狄克斯特拉算法,找出加权图中前往X的最短路径: 介绍图中的环,它导致狄克斯特拉算法不管 ...

  4. 狄克斯特拉算法 - 学习整理

    个人整理,原创发布,转载请标注博客来源.https://editor.csdn.net/md/?articleId=102799813 很多时候,总会忽略了一些你认为不需要的知识体系,但最终你发现,你 ...

  5. 初学狄克斯特拉算法~(待提高)

    读书笔记 狄克斯特拉算用来寻找加权图的"最短路径"(不一定是段数最少,我们需要一定的量度,比如说最少花费,最短时间等,bfs只是解决了段数的最短路径问题) 鉴于无向图就是一个环,而 ...

  6. 算法图解part7:狄克斯特拉算法

    算法图解part7:狄克斯特拉(Dijkstra)算法 1.狄克斯特拉算法(Dijkstra's algorithm) 2.术语 3.负权边 4.实现狄克斯特拉算法 4.1 最短路径思路 4.2 py ...

  7. 迪杰斯特拉算法c++_《算法图解》学习记录7--迪杰斯特拉算法

    本章内容  继续图的讨论,介绍加权图--提高或降低某些边的权重.  介绍狄克斯特拉dijstra算法,让你能够找出加权图中前往X的最短路径.  介绍图中的环,它导致狄克斯特拉算法不管用. 在前一 ...

  8. 小白的算法初识课堂(part7)--狄克斯特拉算法

    学习笔记 学习书目:<算法图解>- Aditya Bhargava 文章目录 狄克斯特拉算法 具体步骤实现 术语 跳蚤市场 具体步骤实现 负权边 python实现 狄克斯特拉算法 在上一个 ...

  9. 算法(四):图解狄克斯特拉算法

    算法简介 狄克斯特拉算法(Dijkstra )用于计算出不存在非负权重的情况下,起点到各个节点的最短距离 可用于解决2类问题: 从A出发是否存在到达B的路径: 从A出发到达B的最短路径(时间最少.或者 ...

最新文章

  1. 你见过最差的算法工程师什么样?
  2. Spring Boot定时任务应用实践
  3. QML自定义图表图例
  4. 如何配置html prettify,[HTML] Prettify 代码高亮使用总结
  5. Web前端开发笔记——第二章 HTML语言 第四节 超链接标签
  6. web应用程序并发测试_测试并发应用
  7. java 格式化时间计算
  8. mysql union 不同字段_mysql中union和union all的区别和注意点
  9. python基础教程廖雪峰云-为什么看不懂廖雪峰的Python学习教程?
  10. spf13-vim安装与使用
  11. Python基于wordnet实现词语相似度计算分析
  12. “会用LabVIEW,但是却没有听说TestStand,好像有点说不过去吧!”(下)
  13. informix数据库维护常用命令
  14. (附源码)计算机毕业设计SSM教务排课管理系统
  15. INTELLIJ IDEA 2017 破解教程(2018也可以!)
  16. 更有效的编写QQ空间、CSDN、博客园图文并茂的文章
  17. ElasticSearch安装IK分词器并使用IK分词器和Kibana进行自定义词汇
  18. matplotlib plot画图不弹框
  19. 一文读懂BLOB算法
  20. 部分HTTPS网站无法访问的可能原因

热门文章

  1. uniapp 电商app 下载页面功能实现
  2. 自建工单(审批流)系统设计
  3. 明星热图|王嘉尔、刘诗诗代言新品牌;王一博、周笔畅、刘恺威出席活动;吴彦祖、黄晓明演绎品牌大片...
  4. 香港中文大学助理教授周博磊:十年之间的CVPR与我们
  5. 2021 回头看看这一年
  6. 虚拟机安装与配置<3>---VMware 16.0上调整虚拟电脑的配置
  7. jy-11-AJAX--承租红+成恒
  8. 生产者剩余的几何解释
  9. 【CYH-02】NOIp考砸后虐题赛:转换式:题解
  10. 信息[http-nio-80-exec-9] org. apache. coyote. http11. Httpl1Processor.service解析注意:HTTP请求解析错误的进--步发生将记录