dijkstra 算法 典型的最短路径算法、用于计算一个节点到其他节点到最短路径 。
主要特点是以起始点为中心向外层层扩散(广度优先搜索思想)、直到扩展到终点为止 。
通过dijkstra 计算图G中的最短路径时、需要指定起点s(即从顶点s开始计算)
此外还需要引进两个集合S 和 U。S的作用是记录已求出最短路径的顶点、而U则是记录还没求出最短路径的顶点
初始时、S中只有起点s,U中除了s之外的顶点、并且U中顶点的路径是起点s到该顶点到路径。然后从U中找出路径最短的顶点、然后将其加入到S中;接着更新U中的顶点和顶点(刚刚放到S集合的顶点)对应的路径,然后再从U中找出路径最短的顶点、然后加入到S中、然后更新U中的顶点......
(1) 初始时,S只包含起点s;U包含除s外的其他顶点,且U中顶点的距离为"起点s到该顶点的距离"[例如,U中顶点v的距离为(s,v)的长度,然后s和v不相邻,则v的距离为∞]。
(2) 从U中选出"距离最短的顶点k",并将顶点k加入到S中;同时,从U中移除顶点k。
(3) 更新U中各个顶点到起点s的距离。之所以更新U中顶点的距离,是由于上一步中确定了k是求出最短路径的顶点,从而可以利用k来更新其它顶点的距离;例如,(s,v)的距离可能大于(s,k)+(k,v)的距离。
(4) 重复步骤(2)和(3),直到遍历完所有顶点。
/** * 顶点 * @author jinxiong */public class Vertex implements Comparable{ private String name; /** * 是否已经算出最短路径 */ private boolean shortest; /** * 与这个顶点相关的边 */ private List edges; /** * 计算出最短路径时、这个节点对应的上一个节点是啥、用于最后用于计算一条完整的路径 */ private Vertex preVertex; /** * 这个节点距离起始节点的距离 */ private int distance = Integer.MAX_VALUE; public Vertex(String name) { this.name = name; edges = new ArrayList<>(); } @Override public int compareTo(Vertex other) { return distance - other.getDistance(); } @Override public String toString() { return name; } public void addNeighbour(Edge edge) { edges.add(edge); }}
/** * 边 * * @author jinxiong */public class Edge { public Edge(int weight, Vertex source, Vertex target) { this.weight = weight; this.source = source; this.target = target; } private int weight; private Vertex source; private Vertex target;}
public class DijkstraShortestPath { public void calculate(Vertex startVertex) { PriorityQueue vertices = new PriorityQueue<>(); startVertex.setDistance(0); // 加入到S集合中 startVertex.setShortest(true); vertices.offer(startVertex); while (!vertices.isEmpty()) { Vertex sourceVertex = vertices.poll(); // 这个vertex都是这些边的起始 for (Edge edge : sourceVertex.getEdges()) { Vertex targetVertex = edge.getTarget(); // 已经计算出的、 if (targetVertex.isShortest()) { continue; } int distance = targetVertex.getDistance(); int newDistance = sourceVertex.getDistance() + edge.getWeight(); if (newDistance < distance) { targetVertex.setDistance(newDistance); vertices.add(targetVertex); targetVertex.setPreVertex(sourceVertex); } } // 加入到S集合中 sourceVertex.setShortest(true); } } /** * 路径、起始就是反转列表 * @param vertex * @return */ public ListgetShortestPathTo(Vertex vertex) { List shortestPath = new ArrayList<>(); shortestPath.add(vertex); while (vertex.getPreVertex() != null) { vertex = vertex.getPreVertex(); shortestPath.add(vertex); } Collections.reverse(shortestPath); return shortestPath; }}
public static void main(String[] args) { Vertex vertexA = new Vertex("A"); Vertex vertexB = new Vertex("B"); Vertex vertexC = new Vertex("C"); Vertex vertexD = new Vertex("D"); Vertex vertexE = new Vertex("E"); vertexA.addNeighbour(new Edge(10,vertexA,vertexC)); vertexA.addNeighbour(new Edge(17,vertexA,vertexB)); vertexC.addNeighbour(new Edge(5,vertexC,vertexB)); vertexC.addNeighbour(new Edge(9,vertexC,vertexD)); vertexC.addNeighbour(new Edge(11,vertexC,vertexE)); vertexB.addNeighbour(new Edge(1,vertexB,vertexD)); vertexD.addNeighbour(new Edge(6,vertexD,vertexE)); DijkstraShortestPath shortestPath = new DijkstraShortestPath(); shortestPath.calculate(vertexA); System.out.println("======================================"); System.out.println("Calculating minimum distance"); System.out.println("======================================"); System.out.println("Minimum distance from A to B: "+vertexB.getDistance()); System.out.println("Minimum distance from A to C: "+vertexC.getDistance()); System.out.println("Minimum distance from A to D: "+vertexD.getDistance()); System.out.println("Minimum distance from A to E: "+vertexE.getDistance()); System.out.println("===================== ================="); System.out.println("Calculating Paths"); System.out.println("======================================"); System.out.println("Shortest Path from A to B: "+shortestPath.getShortestPathTo(vertexB)); System.out.println("Shortest Path from A to C: "+shortestPath.getShortestPathTo(vertexC)); System.out.println("Shortest Path from A to D: "+shortestPath.getShortestPathTo(vertexD)); System.out.println("Shortest Path from A to E: "+shortestPath.getShortestPathTo(vertexE)); }
https://www.cnblogs.com/skywang12345/p/3711516.html
https://java2blog.com/dijkstra-java/
https://zhuanlan.zhihu.com/p/33162490