基于优先队列PriorityQueue的Dijstra算法之Java实现

-最近在学习图算法,其中最为经典的就是Dijstra算法,虽然网上有很多用java实现Dijstra算法的代码,但很少使用优先队列进行优化,这段代码是根据《算法导论》一书中所介绍的Dijstra算法的伪代码编写的,简单、通用、高效。

class vertex {
    String name;// 节点名称
    vertex preNode;// 前驱节点
    double distance;// 源节点到该节点的最短路径的估计值
    private HashMap child = new HashMap();// 边的信息,

    public vertex(String node) {
        // TODO Auto-generated constructor stub
        this.name = node;
        initial();// 初始化节点信息
    }

    private void initial() {
        this.distance = Integer.MAX_VALUE;
        this.preNode = null;
    }

    public void setDistance(double distance) {
        this.distance = distance;
    }

    public void setPreNode(vertex preNode) {
        this.preNode = preNode;
    }

    public HashMap getChild() {
        return child;
    }

}

public class Dijkstra {

    Queue Q;// 存储所有节点的优先队列
    List array_list;// 存储最短路径估计最小的节点

    public Dijkstra() {
        // TODO Auto-generated constructor stub
        Q = new PriorityQueue<>(disComparator);
        array_list = new ArrayList<>();
    }

    Comparator disComparator = new Comparator() {
        @Override
        // 以distance作为排序的关键值
        public int compare(vertex node1, vertex node2) {
            if (node1.distance > node2.distance)
                return 1;
            else if (node1.distance == node2.distance)
                return 0;
            else
                return -1;
        }
    };

    public void initialGraphy() {
        vertex S = new vertex("S");
        vertex A = new vertex("A");
        vertex B = new vertex("B");
        vertex C = new vertex("C");
        vertex D = new vertex("D");
        // 构造边
        S.getChild().put(A, 10.0);
        S.getChild().put(C, 5.0);
        A.getChild().put(B, 1.0);
        A.getChild().put(C, 2.0);
        B.getChild().put(D, 4.0);
        C.getChild().put(D, 2.0);
        C.getChild().put(B, 9.0);
        C.getChild().put(A, 3.0);
        D.getChild().put(B, 6.0);
        D.getChild().put(S, 7.0);
        // 设置S为起点
        S.setDistance(0.0);
        // 将所有节点加入优先队列Q中
        Q.offer(S);
        Q.offer(A);
        Q.offer(B);
        Q.offer(C);
        Q.offer(D);
    }

    public void dijstra() {
        vertex node;
        long time = System.currentTimeMillis();
        while ((node = Q.poll()) != null) {
            // 进行松弛
            for (vertex v : node.getChild().keySet()) {
                if (v.distance > node.distance + node.getChild().get(v)) {
                    v.distance = node.distance + node.getChild().get(v);
                    v.setPreNode(node);
                }
            }
            array_list.add(node);
        }
        System.out.println("计算耗时:" + (System.currentTimeMillis() - time) + "ms");
    }

    public void exportPath() {
        for (vertex node : array_list) {
            ArrayList path = new ArrayList<>();
            double shortestDistance = node.distance;
            while (node.preNode != null) {
                path.add(node.name);
                node = node.preNode;
            }
            path.add("S");
            Collections.reverse(path);
            System.out.println(path + "\t最短距离为:" + shortestDistance);
        }
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Dijkstra Dijkstra = new Dijkstra();
        Dijkstra.initialGraphy();
        Dijkstra.dijstra();
        Dijkstra.exportPath();
    }
}

-测试结果如下:
计算耗时:0ms
[S] 最短距离为:0.0
[S, C, D] 最短距离为:7.0
[S, C] 最短距离为:5.0
[S, C, A] 最短距离为:8.0
[S, C, A, B] 最短距离为:9.0

你可能感兴趣的:(算法学习)