什么是Dijkstra

给定一个图,从某点出发到达某点给出最短的路径

比如上述图,从A出发,到其余点的最短路径,返回这样的表

思路

我们先用一个表格记录A到其余点的距离,初始值是A到A的距离为0,与其余点距离正无穷,然后从A出发看可以直接到达的点距离为多少,接着获得距离更新表,有B,C,D,如果比原来的值小,就更新。锁定A点,然后用B,C,D其中一个点为起点再出发找最近的点,如果有更短的路径就更新,比如B到达C是2,而原本A到B为1,现在从起始点到C更短的距离是1+2=3<7所以更新C下的距离。当用了哪一个点,就锁定,以后再也不用它了。剩余的点与上同理。当所有的点都锁死时候,就返回了。



代码

简易版

我们使用图的一般表示法来表示图
图的一般表示法

public static HashMap<Node, Integer> dijkstra1(Node from) {HashMap<Node, Integer> distanceMap = new HashMap<>();//key:从起始点出发到达key//value:从起始点出发到达key的最小距离//如果在表中,没有T的记录,含义是从from出发到T点的距离为正无穷distanceMap.put(from, 0);// 打过对号的点HashSet<Node> selectedNodes = new HashSet<>();//从未选择过的点(selectedNodes之外的)选择距离最小的点,selectedNodes是黑名单,不要从里面选Node minNode = getMinDistanceAndUnselectedNode(distanceMap, selectedNodes);while (minNode != null) {//  原始点  ->  minNode(跳转点)   最小距离distanceint distance = distanceMap.get(minNode);for (Edge edge : minNode.edges) {Node toNode = edge.to;if (!distanceMap.containsKey(toNode)) {distanceMap.put(toNode, distance + edge.weight);} else { // toNode distanceMap.put(edge.to, Math.min(distanceMap.get(toNode), distance + edge.weight));}}selectedNodes.add(minNode);minNode = getMinDistanceAndUnselectedNode(distanceMap, selectedNodes);}return distanceMap;
}public static Node getMinDistanceAndUnselectedNode(HashMap<Node, Integer> distanceMap, HashSet<Node> touchedNodes) {Node minNode = null;int minDistance = Integer.MAX_VALUE;for (Entry<Node, Integer> entry : distanceMap.entrySet()) {Node node = entry.getKey();int distance = entry.getValue();if (!touchedNodes.contains(node) && distance < minDistance) {minNode = node;minDistance = distance;}}return minNode;
}

进阶版

我们找距离最短的点是遍历集合获得的,效率不够高,如果使用小根堆的话,可以不用遍历,直接拿最上面的。但是小根堆也有缺点,那就是不容易修改,所以我们可以自己写一个小根堆。
接下来是分析
小根堆需要的方法:add,update,ignore方法。增加,更新,忽略

public static class NodeRecord {public Node node;public int distance;public NodeRecord(Node node, int distance) {this.node = node;this.distance = distance;}
}public static class NodeHeap {private Node[] nodes; // 实际的堆结构// key 某一个node, value 上面堆中的位置//如果进来之后弹出了,我们记录下标(value)为-1private HashMap<Node, Integer> heapIndexMap;// key 某一个节点, value 从源节点出发到该节点的目前最小距离private HashMap<Node, Integer> distanceMap;private int size; // 堆上有多少个点public NodeHeap(int size) {nodes = new Node[size];heapIndexMap = new HashMap<>();distanceMap = new HashMap<>();size = 0;}public boolean isEmpty() {return size == 0;}// 有一个点叫node,现在发现了一个从源节点出发到达node的距离为distance// 判断要不要更新,如果需要的话,就更新public void addOrUpdateOrIgnore(Node node, int distance) {if (inHeap(node)) {distanceMap.put(node, Math.min(distanceMap.get(node), distance));insertHeapify(node, heapIndexMap.get(node));}if (!isEntered(node)) {nodes[size] = node;heapIndexMap.put(node, size);distanceMap.put(node, distance);insertHeapify(node, size++);}}public NodeRecord pop() {NodeRecord nodeRecord = new NodeRecord(nodes[0], distanceMap.get(nodes[0]));swap(0, size - 1);heapIndexMap.put(nodes[size - 1], -1);distanceMap.remove(nodes[size - 1]);// free C++同学还要把原本堆顶节点析构,对java同学不必nodes[size - 1] = null;heapify(0, --size);return nodeRecord;}private void insertHeapify(Node node, int index) {while (distanceMap.get(nodes[index]) < distanceMap.get(nodes[(index - 1) / 2])) {swap(index, (index - 1) / 2);index = (index - 1) / 2;}}private void heapify(int index, int size) {int left = index * 2 + 1;while (left < size) {int smallest = left + 1 < size && distanceMap.get(nodes[left + 1]) < distanceMap.get(nodes[left])? left + 1: left;smallest = distanceMap.get(nodes[smallest]) < distanceMap.get(nodes[index]) ? smallest : index;if (smallest == index) {break;}swap(smallest, index);index = smallest;left = index * 2 + 1;}}//返回点有没有进来过private boolean isEntered(Node node) {return heapIndexMap.containsKey(node);}//判断是否在堆里private boolean inHeap(Node node) {return isEntered(node) && heapIndexMap.get(node) != -1;}private void swap(int index1, int index2) {heapIndexMap.put(nodes[index1], index2);heapIndexMap.put(nodes[index2], index1);Node tmp = nodes[index1];nodes[index1] = nodes[index2];nodes[index2] = tmp;}
}// 改进后的dijkstra算法
// 从head出发,所有head能到达的节点,生成到达每个节点的最小路径记录并返回
public static HashMap<Node, Integer> dijkstra2(Node head, int size) {NodeHeap nodeHeap = new NodeHeap(size);nodeHeap.addOrUpdateOrIgnore(head, 0);HashMap<Node, Integer> result = new HashMap<>();while (!nodeHeap.isEmpty()) {NodeRecord record = nodeHeap.pop();Node cur = record.node;int distance = record.distance;for (Edge edge : cur.edges) {nodeHeap.addOrUpdateOrIgnore(edge.to, edge.weight + distance);}result.put(cur, distance);}return result;
}

这个改进之后的算法,我目前还没理解明白,不是太懂,等学完堆和堆排序再回来看一遍把

【图】Dijkstra(迪杰特斯拉)算法、左神Java版相关推荐

  1. Dijkstra迪杰斯特拉算法 C++实现

    本篇文章主要介绍了Dijkstra迪杰斯特拉算法的C++实现,文章包含两个部分,在第一部分中我会简单介绍迪杰斯特拉算法以及一些个人的理解,第二部分会对C++代码的逻辑进行解释.下面是我已经上传的代码资 ...

  2. 最短路径之Dijkstra(迪杰斯特拉)算法(无向图)

    简介      Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.由for循环可知,其时间 ...

  3. MATLAB轻松绘制地图路线——Dijkstra(迪杰斯特拉)算法最短路径规划

    文章目录 1. 地图绘制 2. 计算各节点之间的距离 3. Dijkstra(迪杰斯特拉)算法 4. 根据计算出的距离利用Dijkstra(迪杰斯特拉)算法找出指定节点之间的最短路径 工程文件(可直接 ...

  4. JavaScript实现dijkstra迪杰斯特拉算法(附完整源码)

    JavaScript实现dijkstra迪杰斯特拉算法 PriorityQueue完整源代码 MinHeap.js完整源代码 Heap.js完整源代码 Comparator.js完整源代码 dijks ...

  5. C++实现Dijkstra(迪杰斯特拉)算法(附完整源码)

    C++Dijkstra迪杰斯特拉算法的实现 C++Dijkstra(迪杰斯特拉)算法的完整源码(定义,实现,main函数测试) C++Dijkstra(迪杰斯特拉)算法的完整源码(定义,实现,main ...

  6. Dijkstra(迪杰斯特拉)算法求单源最短路径问题

    Dijkstra(迪杰斯特拉)算法求单源最短路径问题 重要的事情说三遍:代码不是我写的!代码不是我写的!代码不是我写的! 第一个算法是严蔚敏数据结构(C语言版)上写的,第二个算法是王道数据结构上写的, ...

  7. 算法提升:图的Dijkstra(迪杰斯特拉)算法

    目录 概念 思路 代码 概念 迪杰斯特拉算法(Dijkstra)是由荷兰计算机科学家狄克斯特拉于1959年提出的,因此又叫狄克斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路 ...

  8. 最短路径 [迪杰特斯拉算法] ---图

    在网图和非网图中,最短路径的含义是不同的.      -网图是两定点经过的边打上权值之和最少的路径.      -非网图是两顶点之间经过的边数最少的路径. 我们把路径起始的第一个顶点称为源点,最后一个 ...

  9. dijkstra迪杰斯特拉算法(邻接表法)

    算法简易过程: 迪杰斯特拉算法(朴素) O(n^2) G={V,E} V:点集合 E:边集合 初始化时 令 S={某源点ear}, T=V-S= {其余顶点},T中顶点对应的距离(ear, Vi)值若 ...

  10. Dijkstra(迪杰斯特拉)算法

    一.简介 迪克斯特拉算法又名Dijkstra算法(属于贪心算法).Dijkstra算法是从一节点到其余各节点最短路径计算方法. 迪杰斯特拉算法以起始点为中心向外层层扩展,直到扩展到终点为止. 算法思想 ...

最新文章

  1. Windows Server 2012 存储 (四) SMB 对SQL 数据库和Hyper-V的支持
  2. spark rdd saveAsTextFile保存为文件
  3. 在php中type有几种属性,HTML表单之input元素的23种type类型
  4. 生成javascript正则表达式语法图
  5. java实现将一个正整数分解质因数,Java将一个正整数分解质因数
  6. 类加载器 jboss_JBoss AS 7类加载说明
  7. python 多线程为什么鸡肋?
  8. 初识react(四) react中异步解决方案之 redux-saga
  9. 终端terminal的颜色配置
  10. setup2go制作安装程序
  11. 深入解析NAS设备的应用
  12. 预测纽约出租车行程时间
  13. 《Linux 系列》- 常用命令- 文件浏览命令]
  14. Exchange Server 2013文档系列之四: Exchange Server 2013在Windows 2008 R2下部署
  15. Clover引导简明教程
  16. 将老电脑从windows xp系统升级到10//将win10 32位系统更为64位
  17. 用html制作简单考试系统,巧用EXCEL制作模拟考试系统
  18. Android OAID 获取 基于MSA oaid_sdk_1.0.25.zip
  19. 如何用卡诺图化简带有约束条件的逻辑函数?
  20. 使用JS调用迅雷下载网站本地视频,生成迅雷下载链接

热门文章

  1. JESD204接口调试总结——JESD204+In-system-ibert
  2. python做FPGA EG01约束文件文本格式批量更改
  3. linux常用命令加实例大全
  4. java part part_Java Nashorn--Part 5
  5. linux电脑mac地址修改,linux修改MAC地址/localeLinux -电脑资料
  6. c语言生成随机数(组)
  7. Java打印1900年到2100年之间的闰年,一行打印4个
  8. 中国的第一封EMAIL与GOOGLE之退出
  9. 开源 串口调试助手 BaoYuanSerial 使用教程
  10. 优傲协作机器人变身“火眼金睛”质检员