单源最短路径算法-Dijkstra

    xiaoxiao2026-05-21  10

    描述:

    1)算法思想原理:

         Floyd算法是一个经典的动态规划算法。用通俗的语言来描述的话,首先我们的目标是寻找从点i到点j的最短路径。从动态规划的角度看问题,我们需要为这个目标重新做一个诠释(这个诠释正是动态规划最富创造力的精华所在)

          从任意节点i到任意节点j的最短路径不外乎2种可能,1是直接从i到j,2是从i经过若干个节点k到j。所以,我们假设Dis(i,j)为节点u到节点v的最短路径的距离,对于每一个节点k,我们检查Dis(i,k) + Dis(k,j) < Dis(i,j)是否成立,如果成立,证明从i到k再到j的路径比i直接到j的路径短,我们便设置Dis(i,j) = Dis(i,k) + Dis(k,j),这样一来,当我们遍历完所有节点k,Dis(i,j)中记录的便是i到j的最短路径的距离。

    2).算法描述:

    a.从任意一条单边路径开始。所有两点之间的距离是边的权,如果两点之间没有边相连,则权为无穷大。   

    b.对于每一对顶点 u 和 v,看看是否存在一个顶点 w 使得从 u 到 w 再到 v 比己知的路径更短。如果是更新它。

    Dijkstra算法:用于计算图中某一点到其他各点的最短路径。关于Dijkstra算法的说明可以参考 数据结构相关书籍。 为Dijkstra算法设计的类: 1. Node        节点类

    2. Edge        边类 3. Graph       图类 4. Dijkstra     Dijkstra算法类 --------------------------------------------------------------------------------------------------------------------------------- Node类: Java代码   package com.sabrina.dijkstra;      import java.util.ArrayList;   import java.util.List;      public class Node {          // 节点编号       private String id;       // 从当前节点出发的边的信息列表       private List outEdges;             public Node(String id) {           this.id = id;           outEdges = new ArrayList();       }             public void addOutEdge(Edge edge) {           if(edge != null)               outEdges.add(edge);       }          public String getId() {           return id;       }          public void setId(String id) {           this.id = id;       }          public List getOutEdges() {           return outEdges;       }          public void setOutEdges(List outEdges) {           this.outEdges = outEdges;       }   }     Edge类: Java代码   package com.sabrina.dijkstra;      public class Edge {          // 边的起始节点编号       private String startNodeID;       // 边的末尾节点编号       private String endNodeID;       // 边的权值       private double weight;             public String getStartNodeID() {           return startNodeID;       }       public void setStartNodeID(String startNodeID) {           this.startNodeID = startNodeID;       }       public String getEndNodeID() {           return endNodeID;       }       public void setEndNodeID(String endNodeID) {           this.endNodeID = endNodeID;       }       public double getWeight() {           return weight;       }       public void setWeight(double weight) {           this.weight = weight;       }   }     Graph类:   Java代码   package com.sabrina.dijkstra;      import java.util.ArrayList;   import java.util.List;      public class Graph {          // 图中的节点列表       public List nodeList = null;          public Graph() {           nodeList = new ArrayList();       }          public List getNodeList() {           return nodeList;       }          // initialize       public void init() {           // ************************ Node A ***********************           Node aNode = new Node("A");           nodeList.add(aNode);           // A -> B           Edge a2bEdge = new Edge();           a2bEdge.setStartNodeID(aNode.getId());           a2bEdge.setEndNodeID("B");           a2bEdge.setWeight(10);           aNode.addOutEdge(a2bEdge);           // A -> C           Edge a2cEdge = new Edge();           a2cEdge.setStartNodeID(aNode.getId());           a2cEdge.setEndNodeID("C");           a2cEdge.setWeight(20);           aNode.addOutEdge(a2cEdge);           // A -> E           Edge a2eEdge = new Edge();           a2eEdge.setStartNodeID(aNode.getId());           a2eEdge.setEndNodeID("E");           a2eEdge.setWeight(30);           aNode.addOutEdge(a2eEdge);              // ************************ Node B ***********************           Node bNode = new Node("B");           nodeList.add(bNode);           // B -> C           Edge b2cEdge = new Edge();           b2cEdge.setStartNodeID(bNode.getId());           b2cEdge.setEndNodeID("C");           b2cEdge.setWeight(5);           bNode.addOutEdge(b2cEdge);           // B -> E           Edge b2eEdge = new Edge();           b2eEdge.setStartNodeID(bNode.getId());           b2eEdge.setEndNodeID("E");           b2eEdge.setWeight(10);           bNode.addOutEdge(b2eEdge);              // ************************ Node C ***********************           Node cNode = new Node("C");           nodeList.add(cNode);           // C -> D           Edge c2dEdge = new Edge();           c2dEdge.setStartNodeID(cNode.getId());           c2dEdge.setEndNodeID("D");           c2dEdge.setWeight(30);           cNode.addOutEdge(c2dEdge);                     // ************************ Node D ***********************           Node dNode = new Node("D");           nodeList.add(dNode);                     // ************************ Node E ***********************           Node eNode = new Node("E");           nodeList.add(eNode);           // E -> D           Edge e2dEdge = new Edge();           e2dEdge.setStartNodeID(eNode.getId());           e2dEdge.setEndNodeID("D");           e2dEdge.setWeight(20);           eNode.addOutEdge(e2dEdge);                 }   }     Dijkstra类: Java代码   package com.sabrina.dijkstra;      import java.util.ArrayList;   import java.util.HashMap;   import java.util.Iterator;   import java.util.List;   import java.util.Map;      public class Dijkstra {          // 起始节点编号       private String startNodeID;       // 未被处理的节点集合       private List sourceNodeIDList = null;       // 已被处理的节点集合       private List desNodeIDList = null;          // '节点编号' 和  '起始节点与当前节点之间的最短路径' 的映射关系       private Map nodeidShortestRouteMapping = null;       // '节点编号' 和  '起始节点到当前节点之间的最短路径 的 上一跳节点编号' 的映射关系       private Map nodeidLastNodeidMapping = null;       // '节点编号' 和  '节点对象'的 映射关系       private Map idNodeMapping = null;             public Dijkstra(Graph graph, String startNodeID) {           this.startNodeID = startNodeID;                     // 初始化           sourceNodeIDList = new ArrayList();           desNodeIDList = new ArrayList();           nodeidShortestRouteMapping = new HashMap();           nodeidLastNodeidMapping = new HashMap();           idNodeMapping = new HashMap();                     for(Node node : graph.getNodeList()) {               if(node.getId().equals(startNodeID)) {                   desNodeIDList.add(startNodeID);                   // 起始节点到起始节点的最短路径长度为0                   nodeidShortestRouteMapping.put(startNodeID, 0d);               }               else {                   sourceNodeIDList.add(node.getId());                   // 非起始节点到起始节点的最短路径长度为 '无穷大'                   nodeidShortestRouteMapping.put(node.getId(), Double.MAX_VALUE);               }               // 设置到节点最短路径的上一跳节点为'null'               nodeidLastNodeidMapping.put(node.getId(), null);               idNodeMapping.put(node.getId(), node);           }       }             public void start() {           Node nextNode = null;           Node currentNode = null;           String nextNodeID = "";           do {               if(nextNode == null) {                   currentNode = idNodeMapping.get(startNodeID);               }               else {                   currentNode = nextNode;               }               nextNodeID = getNextNode(currentNode);                             nextNode = idNodeMapping.get(nextNodeID);               System.out.println("nextNode.id:" + nextNode.getId());                             sourceNodeIDList.remove(nextNode.getId());               System.out.println("sourceNodeIDList:" + sourceNodeIDList.toString());           } while(sourceNodeIDList.size() > 0);       }                   public String getNextNode(Node currentNode) {           System.out.println("============= currentNode.id: " + currentNode.getId() + " =============");           double shortestPath = Double.MAX_VALUE;           String nextNodeID = "";           //  遍历从当前节点出发的邻接节点           for(Edge nextEdge : currentNode.getOutEdges()) {               System.out.println("nextEdge.endNodeid:" + nextEdge.getEndNodeID());               // 判断 '经过当前节点至邻接节点的距离' < '之前记录的从源节点出发到邻接节点的距离'               if((nextEdge.getWeight() + nodeidShortestRouteMapping.get(currentNode.getId()))                       < nodeidShortestRouteMapping.get(nextEdge.getEndNodeID())) {                   // 更新路由表                   nodeidShortestRouteMapping.put(nextEdge.getEndNodeID(),                           nextEdge.getWeight() + nodeidShortestRouteMapping.get(currentNode.getId()));                   nodeidLastNodeidMapping.put(nextEdge.getEndNodeID(),                           currentNode.getId());               }           }           // 从未被处理过的节点集合中,取出权值最小的节点           for(String nodeID : sourceNodeIDList) {               if(nodeidShortestRouteMapping.get(nodeID) < shortestPath) {                   shortestPath = nodeidShortestRouteMapping.get(nodeID);                   nextNodeID = nodeID;               }           }           if(sourceNodeIDList.size() == 1// 从未被处理过的节点集合中,取出最后一个节点               return sourceNodeIDList.get(0);           return nextNodeID;       }                   public Map getNodeidShortestRouteMapping() {           return nodeidShortestRouteMapping;       }          public Map getNodeidLastNodeidMapping() {           return nodeidLastNodeidMapping;       }          public static void main(String[] args) {           Graph graph = new Graph();           graph.init();                     Dijkstra dijkstra = new Dijkstra(graph, "A");           dijkstra.start();              // 打印最终的路由表           Iterator it = dijkstra.getNodeidShortestRouteMapping().keySet().iterator();           while(it.hasNext()) {               String id = it.next();               System.out.println("nodeId: "  + id + ", shortest length: " + dijkstra.getNodeidShortestRouteMapping().get(id)                       + ", last nodeId: " + dijkstra.getNodeidLastNodeidMapping().get(id));           }       }   }     最终执行结果 ============= currentNode.id: A ============= nextEdge.endNodeid:B nextEdge.endNodeid:C nextEdge.endNodeid:E nextNode.id:B sourceNodeIDList:[C, D, E] ============= currentNode.id: B ============= nextEdge.endNodeid:C nextEdge.endNodeid:E nextNode.id:C sourceNodeIDList:[D, E] ============= currentNode.id: C ============= nextEdge.endNodeid:D nextNode.id:E sourceNodeIDList:[D] ============= currentNode.id: E ============= nextEdge.endNodeid:D nextNode.id:D sourceNodeIDList:[] nodeId: D, shortest length: 40.0, last nodeId: E nodeId: E, shortest length: 20.0, last nodeId: B nodeId: A, shortest length: 0.0, last nodeId: null nodeId: B, shortest length: 10.0, last nodeId: A nodeId: C, shortest length: 15.0, last nodeId: B 相关资源:动态规划法实现最短路径问题java代码
    最新回复(0)