`

Java实现Dijkstra算法

阅读更多

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

为Dijkstra算法设计的类:
1. Node        节点类

2. Edge        边类
3. Graph       图类
4. Dijkstra     Dijkstra算法类
---------------------------------------------------------------------------------------------------------------------------------
Node类:
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类:
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类:


 
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类:
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
PS:如有写的不对的,敬请纠正~
  • 大小: 21.9 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics