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算法。

更多

算法和数据结构笔记

参考资料

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

相关内容

热门资讯

微软游戏CEO菲尔·斯宾塞退休... 微软游戏CEO 菲尔·斯宾塞(Phil Spencer)将于 2 月 23 日退休, Xbox 总裁...
贺博生:黄金原油今日行情价格涨... 来源:市场资讯 黄金最新行情趋势分析: 2月19日,黄金消息面解析:周四亚洲时段,金价在4960美元...
比特币到底怎么买?这份攻略让你... >>点击获取下载地址<< 你是不是也动过买比特币的念头,却被各种术语和平台搞得晕头转向?别急,这篇指...
原创 拿... 最近科技圈出了个大洋相。这事儿看得人目瞪口呆。老百姓心里头更是憋着一股火。 2025年年底,美国科技...
原创 蒙... 蒙古奥尤陶勒盖金铜矿是全球瞩目的超级矿藏,距离中国边境仅80公里。其铜储量高达3110万吨,还伴生1...
原创 印... 当人们谈论用油轮运往印度的俄罗斯石油享有巨大折扣时,实际上,这并非指当地炼油厂能获得的优惠。 它们每...
从“中国游”到“中国购”,全球... 假期前四天,海南离岛免税销售额达9.7亿元、增长15.8%;外企纷纷推陈出新抢滩“年味”市场……透过...
春节不打烊!这支年轻烘焙队,把... (来源:中国商报) 转自:中国商报 中国商报(记者 冉隆楠 文/图)在春节前夕的忙碌节奏中,超市俨然...
中国股市赚钱的一种人坦言:炒股... 在股市变化走势中,如何把握住起点掌握利润,以及如何把握住卖点锁定利润,对于每一个投资者来说都至关重要...
原创 马... 楼市发展牵动着万千民众的心弦,它在市场经济中占据着举足轻重的地位。对普通百姓而言,拥有一个稳定的居所...
原创 面... 中国的正月初五,果然非同一般,“财神爷”的作用照耀全球,给全球各国带来财运。 点开新闻一看,一则令...
美国1750亿美元关税退税,对... 序言:一场意外的“春雨” 2026年2月,美国最高法院一纸判决,把特朗普推上了风口浪尖。 6比3,特...
康曼德资本董事长丁楹:马年新程... 岁序更替,万象更新。农历马年春节已至,回望刚刚过去的2025年,中国资本市场在波动与修复中不断寻找新...
实体女装店必看!低成本获客不烧... 做实体女装店的姐妹谁懂啊?房租、货款压得喘不过气,想靠小红书引流,却要么不会做内容,要么花大价钱投流...
去中心化金融世界的语言桥梁:深... 随着区块链技术的快速发展,去中心化交易所逐渐成为数字资产交易的重要基础设施。作为去中心化金融生态中的...
瞄准压岁钱 多家银行推儿童专属... 据统计,包括广发银行、苏州银行、北京农商银行等在内的多家金融机构推出儿童专属银行卡、亲子账户管理、少...
金银价再度大涨!国内金饰价格逼... 2月21日是正月初五,按照传统习俗是迎财神的日子,国际金银价格也在这一天迎来上涨。其中现货黄金价格重...
绿云软件,来自浙江杭州,递交I... 2026年2月20日,来自浙江杭州西湖区的杭州绿云软件股份有限公司Hangzhou GreenClo...
OpenAI,突传大消息! 每经编辑|张锦河 2月20日,据媒体报道,OpenAI正在重新设定其资本支出预期。OpenAI向投...
原创 二... 近期,中国房地产市场正经历一场显著的调整,呈现出“量价齐跌”的态势。最新数据显示,5月份全国百城新建...