一、汇总
算法 | 场景 | 说明 | 参考 | BFS | 树
无权图的搜刮
| 标准BFS默认搜刮一条最短路径
改造后可以输出全部最短路径
| https://blog.csdn.net/m0_37145844/article/details/144534202 | DFS | 走迷宫 | 重要利用回溯算法思想,不包管最短路径 | https://blog.csdn.net/m0_37145844/article/details/144534202 | | 带权图最短路径的经典解法 | 重要利用贪心思想,其中在u打印路径时候包含递归,回溯等思想 | 本篇解说 | 二、Dijkstra 原理
借助java工具类:PriorityQueue 默认内部元素逼迫根据指定规则举行自然排序的的小顶堆,每次选择下层节点到起点开始算的最小权值的节点作为当前节点,举行向外的下一个层级的探索,最终让全部节点都保存了,此节点从开始节点的最小权重值及其最短路径的父节点。
三、Dijkstra 代码实现-Java版本
有必要解说一下代码结构:
- 内部类的利用
- 表现更强的封装性,结构体仅供外部类利用,不对外袒露。
- 外部类可以直接调用内部类,简化代码。
- 内部类也可以直接利用外部类的成员变量,此例子中暂无表现。
- 优先级队列的利用
- 比力器的构造。
- 因为每次向外层探索时候,都会加入下一层到开始节点权重总和最小的节点,此数据结构逼迫举行排序,序列化为一个小顶堆。这也是提升此算法性能的关键设计。
- 默认为小顶堆。
- 间隔Map和路径反向记录Map,都表现了算法设计的技巧。
- 尤其在打印路径时候,最终用递归思想。
- package algo.backtrace.Dijkstra.weiwei;
- import java.util.*;
- public class Dijkstra {
- class Grap {
- // 带权重的无向图表示,邻接矩阵表示
- Map<Integer, List<Edag>> adjList;
- Grap() {
- adjList = new HashMap<>();
- }
- // 添加边
- public void addEdag(int start, int des, int weight) {
- adjList.putIfAbsent(start, new ArrayList<>());
- adjList.putIfAbsent(des, new ArrayList<>());
- adjList.get(start).add(new Edag(des, weight));
- adjList.get(des).add(new Edag(start, weight));
- }
- // 获取一个顶点的所有边
- public List<Edag> getEdags(int node) {
- return adjList.getOrDefault(node, new ArrayList<>());
- }
- // 获取所有顶点
- public Set<Integer> getAllNodes() {
- return adjList.keySet();
- }
- }
- // 描述边
- class Edag{
- int des;
- int weight;
- Edag(int des, int weight) {
- this.des = des;
- this.weight = weight;
- }
- }
- public Map<Integer, Integer> dijkstra(Grap grap, Integer start) {
- // 定义工具
- PriorityQueue<int[]> pq = new PriorityQueue<>(Comparator.comparing(a -> a[1]));
- Map<Integer, Integer> dist = new HashMap<>();
- Map<Integer, Integer> prev = new HashMap<>();
- // 初始化参数
- for (Integer node : grap.getAllNodes()) {
- dist.put(node, Integer.MAX_VALUE);
- prev.put(node, -1);
- }
- dist.put(start, 0);
- pq.offer(new int[]{start, 0});
- while (!pq.isEmpty()) {
- int[] poll = pq.poll();
- int currNode = poll[0];
- int currWeight = poll[1];
- if (currWeight > dist.get(currNode)) {
- continue;
- }
- for (Edag edag : grap.getEdags(currNode)) {
- int newDist = currWeight + edag.weight;
- if (newDist < dist.get(edag.des)) {
- dist.put(edag.des, newDist);
- prev.put(edag.des, currNode);
- pq.offer(new int[]{edag.des, newDist});
- }
- }
- }
- System.out.println("dist:" + dist);
- System.out.println("prev:" + prev);
- return prev;
- }
- public void printTrace(Map<Integer, Integer> prevMap, int traget, List<Integer> trace) {
- if (prevMap.get(traget) == -1) {
- return;
- }
- traget = prevMap.get(traget);
- printTrace(prevMap, traget, trace);
- trace.add(traget);
- }
- public void main(String[] args) {
- Grap grap = new Grap();
- grap.addEdag(0,1,4);
- grap.addEdag(0,2,1);
- grap.addEdag(1,3,2);
- grap.addEdag(2,3,8);
- grap.addEdag(2,4,3);
- grap.addEdag(4,5,2);
- grap.addEdag(3,5,1);
- Dijkstra dijkstra = new Dijkstra();
- Map<Integer, Integer> prevMap = dijkstra.dijkstra(grap, 0);
- List<Integer> list = new ArrayList<>();
- dijkstra.printTrace(prevMap, 5, list);
- System.out.println(list);
- }
- }
- // 输出
- // dist:{0=0, 1=4, 2=1, 3=6, 4=4, 5=6}
- // prev:{0=-1, 1=0, 2=0, 3=1, 4=2, 5=4}
- // [0, 2, 4] 瑕疵之处是traget 没有打印出,无伤大雅。
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |