17.6:迪瑞克斯啦算法

news/2024/10/30 13:31:28/

迪瑞克斯啦算法

这个算法研究的是:有向的,没有负权重,可以有环的图。

在这里插入图片描述

这个算法主要研究的是:给出的节点到这张图的其他节点的最短路径是多少。用一个表表示出来。

在这里插入图片描述

思路:

如下图所示,我们想要求出a节点到其他节点的最小路径分别是多少。

刚开始a可以直接到b,c,d点,不能到e点,所以表里记录着:(d,2) ,(c,6) ,(b,1) ,(e,无穷)

从里面选一个最小的,选出b来,现在,a到c的距离可以是3,a到e的距离可以是7,表里的数据刷新一下。

注意此时**(b,1)就被锁定了,a到b的最短距离就是1**,往后循环此操作,直至剩下所有节点都被锁定。

锁定这个地方是最精妙的。解释 —> : 在刚开始的时候,a到b的距离是1,a到c的距离是6,a到d的距离是2,a到e的距离是正无穷。最小的就是a到b的距离。此时就把a到b的最小距离定为1.,原因是:我之所以从表中每次都挑选最小的距离节点是因为我想找找到其他节点的还有没有最短的路径。而之所以选出最小的距离节点之后,就将这个键值对锁定是因为从a到这个节点一定是最小的,因为其他的距离都比他大,加之没有负权重,所以不可能有比他更小的了。

使用到的容器:

map:存放表中数据。

堆:筛选最小距离节点。//发现堆结构还不行,因为表中的数据是会刷新的,而堆结构不会自动更改结构,所以必须是加强堆才可以。

在这里插入图片描述

package algorithmbasic.class17;import java.util.HashMap;public class Dijkstra {//从head出发,所有head能到达的节点,生成到达每个节点的最小路径记录并返回public static HashMap<Node, Integer> dijkstra(Node head, int size) {//result记录最终要返回的结果。HashMap<Node, Integer> result = new HashMap<>();//创建好我的加强堆HeapGreater heapGreater = new HeapGreater(size);//遍历head节点的直接连接节点。for (Edge edge : head.edges) {heapGreater.addOrUpdateOrIgnore(edge.to, edge.weight);}while (!heapGreater.isEmpty()) {Record record = heapGreater.poll();result.put(record.node, record.distance);for (Edge edge : record.node.edges) {heapGreater.addOrUpdateOrIgnore(edge.to, edge.weight + record.distance);}}return result;}/*** Record内部类* 之所以创建这个内部类是因为:我想将节点与权重当作一个整体,通过加强堆的排序之后弹出的是一个整体,这样方便* 当然使用hashmap也可以。*/public static class Record {public Node node;public int distance;public Record(Node node, int distance) {this.node = node;this.distance = distance;}}public static class HeapGreater {/*** 属性*/Node[] nodes;//记录node所对应的位置。//如果这个node被弹出了,heapIndexMap中这个节点所对应的位置就定为 -1.原因是:便于我们判断这个节点来过。//之所以必须判断这个节点来过是因为,如果后面的某个节点的直接连接节点还是这个节点,如果没有这个判断,这个节点还会再一次的进入堆中//导致最终返回的map中正确的值被覆盖。HashMap<Node, Integer> heapIndexMap;//记录剩余节点的a到Node所对应的最小距离HashMap<Node, Integer> distanceMap;int usedSize;/*** 构造器*/public HeapGreater(int size) {nodes = new Node[size];heapIndexMap = new HashMap<>();distanceMap = new HashMap<>();usedSize = 0;}/*** addOrUpdateOrIgnore方法* 传进来的是一个节点,以及a到该节点的距离。* 对于这个节点只会出现三种操作,要么这个节点已经被处理过了,那就不用管直接跳过,* 要么这个节点从来没有进来过,那就放入堆中,* 要么这个节点的a到该节点的距离比堆中记录的要小,那就更新堆中的记录。*/public void addOrUpdateOrIgnore(Node node, int weight) {//传进来的节点要不就放入加强堆中,要不就更新加强堆中的值,要么就被忽略。//如果这个节点在堆中,看看a到该节点的距离比堆中记录的要小,那就更新堆中的记录。if (inHeap(node)) {distanceMap.put(node, Math.min(weight, distanceMap.get(node)));//因为堆中的记录只会变的更小,所以只会向上调整。insertHeapify(heapIndexMap.get(node));}//这个节点从来没有进来过。//那就加入这个节点。if (!isEntered(node)) {nodes[usedSize] = node;distanceMap.put(node, weight);heapIndexMap.put(node, usedSize);insertHeapify(usedSize++);}}/*** 向上调整*/private void insertHeapify(int index) {int father = (index - 1) / 2;while (distanceMap.get(nodes[father]) < distanceMap.get(nodes[index])) {swap(nodes, father, index);index = father;father = (index - 1) / 2;}}public void swap(Node[] nodes, int fatehr, int index) {heapIndexMap.put(nodes[fatehr], index);heapIndexMap.put(nodes[index], fatehr);Node temp = nodes[fatehr];nodes[fatehr] = nodes[index];nodes[index] = temp;}/*** 向下调整*/private void heapify(int index, int size) {int lc = index * 2 + 1;while (lc < size) {int smallChild = lc + 1 < size ? (distanceMap.get(nodes[lc]) < distanceMap.get(nodes[lc + 1]) ? lc : lc + 1) : (lc);if (distanceMap.get(index) > distanceMap.get(smallChild)) {swap(nodes, index, smallChild);index = smallChild;lc = index * 2 + 1;} else {break;}}}/*** 判断当前节点是否进来过。*/private boolean isEntered(Node node) {return heapIndexMap.containsKey(node);}/*** 判断当前节点是否在堆上*/private boolean inHeap(Node node) {return isEntered(node) && heapIndexMap.get(node) != -1;}/*** poll()方法*/public Record poll() {Record record = new Record(nodes[0], distanceMap.get(nodes[0]));distanceMap.remove(nodes[0]);heapIndexMap.put(nodes[0], -1);swap(nodes, 0, usedSize - 1);heapify(0, --usedSize);return record;}/*** isEmpty()方法*/public boolean isEmpty() {return this.usedSize == 0;}}
}

http://www.ppmy.cn/news/281066.html

相关文章

dpdk rte_ring

rte_ring_enqueue卡住是什么原因 以下回答来自于GPT-3.5&#xff1a; 如果程序卡在rte_ring_enqueue函数&#xff0c;可能有几种原因。首先&#xff0c;rte_ring_enqueue函数可能会阻塞&#xff0c;直到有空间可用于将数据包添加到环形缓冲区中。如果环形缓冲区已满&#xff0…

核心领域的数字基建梳理

数字基建&#xff1a;新基建的核心 数字基建是数字经济发展的重要底座&#xff0c;《“十四五”数字经济发展规划》的首要重要任务就是“优化升级数字基础设施”&#xff0c;并提出要建设高速泛在、天地一体、云网融合、智能敏捷、绿色低碳、安全可控的智能化综合性数字信息基…

计算机组装配件选择,组装电脑选配件时需要注意哪几方面?

1、选择一线品牌的主板&#xff1a;华硕、技嘉、微星。型号尽量不要选择太低端的&#xff0c;500元左右的主板就可以了。 2、选择原封的CPU&#xff0c;质量有保证&#xff0c;质保也有区别&#xff0c;最好是用INTEL i5或I3双核四线程,如果费用高选择AMD a8、a10系列或者FX系列…

暗夜

喜欢在夜里 煮上一杯咖啡 于是 思绪在涌起 象海上的雾 在升腾 夜里 我会蜕变成诗人 歌颂生命 向往自由 和爱情 天上没有月亮 只有几颗星星闪烁 象困倦的眼 我能挣脱 这暗夜的包围吗 暗自摇头 看那咖啡 已渐渐冷却

计算机主机配置有哪些,组装电脑配置推荐有哪些

组装电脑配置推荐有哪些 在这科技化的时代&#xff0c;电脑已经成为大家日常生活中的常用的设备&#xff0c;然而组装一台适合于自己的高性能电脑&#xff0c;依然是大多数人的首选。那么组装电脑配置推荐有哪些呢?下面为大家介绍几个不同价位的组装电脑配置推荐&#xff0c;有…

冷冰

话说&#xff0c;每一天的太阳都是新的&#xff0c;却不一定都是温暖的。冬天的夜晚冷冰冰的&#xff0c;无法入眠。

打游戏计算机 配置清单,组装电脑配置清单玩游戏用的

技嘉 GA-780T-USB3 (芯片组AMD760/AM3)主板 全固态电容 500 AMD 速龙II X2 250双核CPU 深盒 400 金士顿 DDR3 1333 4G台式机内存条 140 全新320G 西数 蓝盘静音版SATA300 8M 7200转硬盘 240 航嘉 冷静王加强版 额定270W 180 146080块的机箱 显卡 影驰GTS450重炮手显卡 TC1G GDD…

冷漠

有这样一个有趣的实验&#xff1a;美国心理学家为从动物实验中获得有关爱的人类行为线索&#xff0c;为幼猴设计了五种人造母猴&#xff0c;观察“母亲”的拒绝会在幼猴的身上引起怎样的 反应&#xff1a;第一种偶尔用压缩空气吹幼猴&#xff1b;第二种会猛烈晃动&#xff0c;致…