Dijkstra 算法说明与实现
admin
2024-04-21 06:01:13
0

Dijkstra 算法说明与实现

作者:Grey

原文地址:

博客园:Dijkstra 算法说明与实现

CSDN:Dijkstra 算法说明与实现

问题描述

问题:给定出发点,出发点到所有点的距离之和最小是多少?

注:Dijkstra 算法必须指定一个源点,每个边的权值均为非负数,求这个点到其他所有点的最短距离,到不了则为正无穷, 不能有累加和为负数的环。

题目链接见:LeetCode 743. Network Delay Time

主要思路

  1. 生成一个源点到各个点的最小距离表,一开始只有一条记录,即原点到自己的最小距离为0, 源点到其他所有点的最小距离都为正无穷大

  2. 从距离表中拿出没拿过记录里的最小记录,通过这个点发出的边,更新源 点到各个点的最小距离表,不断重复这一步

  3. 源点到所有的点记录如果都被拿过一遍,过程停止,最小距离表得到了。

关键优化:加强堆结构说明

完整代码见:

class Solution {public static int networkDelayTime(int[][] times, int N, int K) {Graph graph = generate(times);Node from = null;for (Node n : graph.nodes.values()) {if (n.value == K) {from = n;}}HashMap map = dijkstra2(from, N);int sum = -1;for (Map.Entry entry : map.entrySet()) {if (entry.getValue() == 0) {N--;continue;}N--;if (entry.getValue() == Integer.MAX_VALUE) {return -1;} else {sum = Math.max(entry.getValue(), sum);}}// 防止出现环的形状//   int[][] times = new int[][]{{1, 2, 1}, {2, 3, 2}, {1, 3, 1}};//        int N = 3;//        int K = 2;if (N != 0) {return -1;}return sum;}public static Graph generate(int[][] times) {Graph graph = new Graph();for (int[] time : times) {int from = time[0];int to = time[1];int weight = time[2];if (!graph.nodes.containsKey(from)) {graph.nodes.put(from, new Node(from));}if (!graph.nodes.containsKey(to)) {graph.nodes.put(to, new Node(to));}Node fromNode = graph.nodes.get(from);Node toNode = graph.nodes.get(to);Edge fromToEdge = new Edge(weight, fromNode, toNode);//Edge toFromEdge = new Edge(weight, toNode, fromNode);fromNode.nexts.add(toNode);fromNode.out++;//fromNode.in++;//toNode.out++;toNode.in++;fromNode.edges.add(fromToEdge);//toNode.edges.add(toFromEdge);graph.edges.add(fromToEdge);//graph.edges.add(toFromEdge);}return graph;}public static class Graph {public HashMap nodes;public HashSet edges;public Graph() {nodes = new HashMap<>();edges = new HashSet<>();}}public static class Edge {public int weight;public Node from;public Node to;public Edge(int weight, Node from, Node to) {this.weight = weight;this.from = from;this.to = to;}}public static class Node {public int value;public int in;public int out;public ArrayList nexts;public ArrayList edges;public Node(int value) {this.value = value;in = 0;out = 0;nexts = new ArrayList<>();edges = new ArrayList<>();}}public static Node getMinNode(HashMap distanceMap, HashSet selectedNodes) {int minDistance = Integer.MAX_VALUE;Node minNode = null;for (Map.Entry entry : distanceMap.entrySet()) {Node n = entry.getKey();int distance = entry.getValue();if (!selectedNodes.contains(n) && distance < minDistance) {minDistance = distance;minNode = n;}}return minNode;}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 上面堆中的位置private HashMap heapIndexMap;// key 某一个节点, value 从源节点出发到该节点的目前最小距离private HashMap 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 dijkstra2(Node head, int size) {NodeHeap nodeHeap = new NodeHeap(size);nodeHeap.addOrUpdateOrIgnore(head, 0);HashMap 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算法。

更多

算法和数据结构笔记

参考资料

算法和数据结构体系班-左程云

相关内容

热门资讯

原创 宁... 由于化肥和天然气的短缺,欧盟委员会正在向欧洲农民建议,尝试用牛粪以及小型牲畜的粪便和尿液,来替代来自...
原创 3... 在情感的迷宫中,每个星座都有其独特的情感语言。今天,让我们以作家的身份,用专业的语气,探讨那些扎心的...
原创 5... 昨天亏的钱今天回来了? 先别急着加仓,看看这些细节你未必注意到。 5月22日(周五),A股高开,随后...
美股收盘:标普连涨八周道指刷新... 财联社5月23日讯(编辑 赵昊)周五(5月22日),受美债收益率回落影响,美股三大指数连三日收升,其...
新规实施在即,A股公司董秘密集... 董秘任职新规即将正式施行,相关的职务变动已提前开启。据财闻不完全统计发现,4月21日至今约130家公...
肾内科举办人工智能助力临床医疗... 在医疗信息化与智能化快速发展的今天,人工智能正逐步成为提升临床工作效率与质量的重要工具。为进一步增强...
坪山人等到了!盒马鲜生坪山首店... 南都讯 记者曾海城5月22日,深圳市坪山区马峦街道悦阾SPACE购物中心迎来七家优质品牌集中签约。其...
港股异动丨AI应用股集体拉升 ... 港股市场AI应用股集体拉升,迅策(3317.HK)午后强势拉升,一度大涨16.4%至264港元,市值...
OpenAI估值冲刺万亿美元I... SpaceX提交招股书的同一天,另一条重磅消息在资本市场快速发酵。据《华尔街日报》等多家媒体报道,O...
拟上市企业股权激励咨询怎么选,... 在拟上市企业的发展进程中,股权激励咨询显得尤为关键。如何选择一家合适的咨询机构,是众多企业面临的重要...
39.44万亿元!当险资规模超... 记者 姜鑫 39.44万亿元——这是2026年第一季度末的保险资金运用余额。同期,公募基金的资产净值...
*ST金科撤销退市及其他风险警... 观点网讯:5月22日,金科地产集团股份有限公司(*ST金科)发布关于申请撤销退市风险警示及其他风险警...
下沉市场餐饮创业选连锁项目有哪... 随着居民日常就餐需求越来越偏向便利化、高性价比,社区周边的便民餐饮赛道逐渐受到创业者和投资者的关注,...
【每周经济观察】市场分化孕育民... 国家统计局最新发布的数据显示,今年前4个月,我国民间固定资产投资同比下降5.2%。乍一看,这个数字确...
一季度赚了4350万元,蔚来能... 本报(chinatimes.net.cn)记者刘凯 北京报道 继2025年第四季度首次实现非美国通用...
“A股不死鸟”600696,确... 公司股票将于2026年6月1日进入退市整理期,预计最后交易日为6月22日,交易期限为15个交易日。退...
富途、老虎双双大跌!分别被罚没... 5月22日下午,证监会官网消息称,近日,证监会依法对Tiger Brokers (NZ) Limit...
原创 中... 在全球稀土市场的博弈中,中国东北冻土下的一个重大发现,犹如一颗重磅炸弹,让海外稀土突围的压力瞬间倍增...
西大门2025年研发投入298... 西大门(605155)披露2025年年度报告。报告期内,公司全年研发投入达2989.83万元,同比下...
AI掉队后,腾讯文档团队被压缩... 5月21日,在多个职场社交平台,有用户发文谈及腾讯文档裁员信息,该用户称腾讯文档业务将取消北京办公地...