Dijkstra算法--单源最短路径问题

Dijkstra以及路径输出

算法原理

Dijkstra算法是利用广度优先搜索思想(BFS)的一种单源最短路径算法,相对于简单粗暴时间复杂度为O(n^3)的Floyed算法,(详情见我另一篇博客 只有五行的Floyed算法及全路径输出),Dijkstra算法的时间复杂度则有好的多,为O(n^2)。

该算法以起点为中心,将相邻边加入到优先队列中,每次取队列中的最短边,利用伸缩操作(relaxation),更新各点到源点的最近距离(这里用到了贪心算法原理), 存入到一个集合disTo中,该集合中记录每一个点到源点的最近距离,在pathTo集合中,设置此节点的上一节点。如果这点没有被访问过,就加入到优先队列中,就这样重复操作层层向外遍历,最后就可以生成一个最短路径树,对于从该源点到某一点的最短路径问题,只要看该点是否被访问过,被访问过的点说明存在最短路径,回溯pathTo集合,如pathTo(A) = B, B是使A到源点距离最近的相邻点(由贪心算法可知),pathTo(B) = C , C是使B到源点距离最近的相邻点,反复操作,直到pathTo(X) = 源点。即可得到最短路径

算法的主要函数

节点类

package Util;

public class Node {
    private int x,y;
    private String name;

    public Node(int x, int y){
        this.x = x;
        this.y = y;
    }

    public Node(int x,int y,String name){
        this.x = x;
        this.y = y;
        this.name = name;
    }


    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public String getName(){
        return name;
    }

    @Override
    public boolean equals(Object o){
        if(o instanceof Node){
            return ((Node) o).getX()==this.x&&((Node) o).getY()==this.getY();
        }
        return false;
    }
}

还有边类与无向图类,代码git

Dijkstra

public void start(){
        if (this.undirectedGraph==null){
            return;
        }
        pq.add(source);
        while(!pq.isEmpty()){
            Node n = pq.poll();
            marked.add(n);
            Iterator<UndirectedEdge> iterator = undirectedGraph.adj(n).iterator();
            while (iterator.hasNext()){
                UndirectedEdge adjNode = iterator.next();
                Node other = adjNode.other(n);
                if(disTo.get(other)>disTo.get(n)+adjNode.getDistance()
                        &&disTo.get(n)!=Integer.MAX_VALUE) {
                    disTo.put(other, disTo.get(n) + adjNode.getDistance());
                    pathTo.put(other,n);
                }
                if(!marked.contains(other))
                    pq.add(other);
            }
        }

实际用例:

public static void main(String[] args) {
        Node[] nodeArrs = {new Node(0,2,"0"),new Node(1,9,"1"),new Node(2,3,"2"),
                new Node(3,4,"3"),new Node(4,5,"4"),new Node(5,6,"5")};
        UndirectedGraph undirectedGraph = new UndirectedGraph(nodeArrs[0],6,8);
        undirectedGraph.addEdge(new UndirectedEdge(nodeArrs[0],nodeArrs[1],15));
        undirectedGraph.addEdge(new UndirectedEdge(nodeArrs[0],nodeArrs[3],5));
        undirectedGraph.addEdge(new UndirectedEdge(nodeArrs[1],nodeArrs[5],6));
        undirectedGraph.addEdge(new UndirectedEdge(nodeArrs[3],nodeArrs[5],20));
        undirectedGraph.addEdge(new UndirectedEdge(nodeArrs[3],nodeArrs[4],30));
        undirectedGraph.addEdge(new UndirectedEdge(nodeArrs[1],nodeArrs[2],15));
        undirectedGraph.addEdge(new UndirectedEdge(nodeArrs[2],nodeArrs[4],10));
        undirectedGraph.addEdge(new UndirectedEdge(nodeArrs[4],nodeArrs[5],9));
        Dijkstra dijkstra = new Dijkstra();
        dijkstra.setUp(undirectedGraph);
        dijkstra.start();
        for(int i = 1;i<nodeArrs.length;i++){
            if (dijkstra.hasPathTo(nodeArrs[i])){
                System.out.print("Node0到Node"+nodeArrs[i].getName()+"的最短路径位:");
                for (Node node:dijkstra.shortestPath(nodeArrs[i])){
                    System.out.print(node.getName()+"->");
                }
                System.out.println(dijkstra.shortestDistance(nodeArrs[i]));
            }
        }
    }

在这里插入图片描述
结果
在这里插入图片描述

完整代码以及其他寻路算法见我github

发布了43 篇原创文章 · 获赞 16 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/include_IT_dog/article/details/88944529