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

更多

算法和数据结构笔记

参考资料

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

相关内容

热门资讯

土耳其拟加入加拿大牵头的防务银... 新华社北京7月14日电 一名土耳其官员13日告诉路透社,土方已通报加拿大,将作为创始成员加入加方牵头...
视频丨VR、实景AI加速落地 ... 国家统计局近日发布数据显示,2025年全年,我国的文化产业营收突破20万亿元,数字驱动的文化新业态引...
把上海外环盘做成“市区爆款”,... 2026年7月9日,由北京中指信息技术研究院主办,中国房地产指数系统、中国物业服务指数系统承办的“中...
美银力挺AMD(AMD.US)... 智通财经APP获悉,美国银行在半导体市场周度展望报告中表示,由于服务器处理器需求“异常旺盛”,AMD...
机器工作,人类生活:财富、劳动... 来源:FT中文网 丹麦投资人特维德谈新作《超级趋势:机器工作,人类生活》。他认为大规模人类劳动将不...
原创 金... 文章里把这一轮下跌的原因先归到美联储头上。 说是新任主席沃什6月议息会后放了信号,年末利率中值抬到3...
病病不病:算法病灶与企业家的心... 引言 “法人,即法律意义上的人。在数智时代,这个人不仅拥有生物属性,更被赋予了‘数字灵魂’。”随着企...
83岁董事长遭女儿女婿“逼宫”... 在公司实控人家族上演着“发难、反转、再博弈”的内斗连环剧,令市场观望情绪升温,7月13日,奥精医疗跌...
国际油价创6年来最大单日涨幅,... 据新华社,由于美伊冲突升级及美国宣布将恢复对伊朗的海上封锁,国际原油期货价格7月13日早盘显著上涨,...
美联储维持100亿美元购债规模... 智通财经APP获悉,美联储周一宣布,在截至8月13日的本轮操作周期内,将继续购买约100亿美元美国国...
A股行情逻辑持续迭代 进入结构... 2026年,A股彻底告别普涨普跌的传统牛市模式,进入“指数震荡、个股分化、热点轮动”的结构性新阶段。...
习酒“脱茅”三年考:2025年... 出品|搜狐财经 作者|李文贤 习酒2025年的成绩单不太好看。 营收150亿,净利润不到18个亿。一...
同泰数字经济股票A:2026年... AI基金同泰数字经济股票A(012696)披露2026年二季报,第二季度基金利润1.06亿元,加权平...
DNA损伤修复|DDR通路研究... DNA损伤修复(DDR)通路是维持基因组稳定性的核心防线,其功能异常与肿瘤发生发展密切相关。近年来,...
一连三轮,上海诞生一家百亿卫星... 来源:投资界 中国开启可回收火箭时代,投资人看上6G最难的一颗芯片。 报道/投资界PEdaily ...
欧洲抢空调,国货、机器人世界杯... 7月14日,海关总署在国新办发布会亮出今年上半年外贸成绩单:货物贸易进出口总额25.47万亿元,同比...
希音国际IPO:小单快反的长期... 摘要:千亿帝国 ID:朝阳资本论 作者:赤眼 作为中国跨境电商出海的标杆企业,中国快时尚跨境电商希...
快讯 | 265亿赴美IPO封... 7月10日,韩国存储芯片龙头SK海力士,正式以ADR形式登陆纳斯达克挂牌交易。 这次上市直接创下历史...
10年2.1%+值得买吗? 债市上半年走出一轮牛市后,投资者正面临新的选择:收益率已降至低位,10年期收益率仍在2.1%以上的信...
天目药业控股股东拟转让20%股... 7月13日, 天目药业(600671.SH)公告称,公司控股股东汇隆华泽持有公司29.99%股份,拟...