【连载】Dijkstra求最短路径算法设计—Java实现

Dijkstra求最短路径算法设计

1. Dijkstra简介

  • What’s the shortest path?

    最短路径指两顶点之间经过的边上权值之和最少的路径,并且称路径上的第一个顶点为源点,最后一个顶点为终点。

  • Thought line of algorithm:

    《【连载】Dijkstra求最短路径算法设计—Java实现》

  • How to realize Dijkstra algorithm:

    《【连载】Dijkstra求最短路径算法设计—Java实现》

2. Let’s coding

注:该代码的实现是基于Java的,也运用了设计模式在里面。所以,如果个人Java基础和设计模式思想不过关,接下来看代码会比较费解,望谅解!

数据结构的构建:
  • Vertex.java
package zychaowill.datastructure.graph.vo;

public class Vertex implements Comparable<Vertex> {
    /** * */
    private String name;

    /** * 最短路径长度 */
    private int path;

    /** * 节点是否已经出列(是否已经处理完毕) */
    private boolean isMarked;

    public Vertex(String name) {
        this.name = name;
        this.path = Integer.MAX_VALUE; // 初始设置为无穷大
        this.setMarked(false);
    }

    public Vertex(String name, int path) {
        this.name = name;
        this.path = path;
        this.setMarked(false);
    }

    @Override
    public int compareTo(Vertex o) {
        return o.path > path ? -1 : 1;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getPath() {
        return path;
    }

    public void setPath(int path) {
        this.path = path;
    }

    public boolean isMarked() {
        return isMarked;
    }

    public void setMarked(boolean isMarked) {
        this.isMarked = isMarked;
    }

}
  • Graph.java
package zychaowill.datastructure.graph.vo;

import java.util.List;

import zychaowill.datastructure.graph.algo.ShortestPathStrategy;

public class Graph {
    /* * 顶点 */
    private final List<Vertex> vertexs;

    /* * 边 */
    private final int[][] edges;

    /** * 求最短路径的策略 */
    private ShortestPathStrategy shortestPathStrategy;

    public Graph(List<Vertex> vertexs, int[][] edges) {
        this.vertexs = vertexs;
        this.edges = edges;
    }

    /* * 打印图 */
    public void printGraph() {
        int verNums = vertexs.size();
        for (int row = 0; row < verNums; row++) {
            for (int col = 0; col < verNums; col++) {
                if (Integer.MAX_VALUE == edges[row][col]) {
                    System.out.print("X");
                    System.out.print(" ");
                    continue;
                }
                System.out.print(edges[row][col]);
                System.out.print(" ");
            }
            System.out.println();
        }
    }

    /** * Get shortest path from v * @see * @param v */
    public void getShortestPath(Vertex v) {
        shortestPathStrategy.shortestPath(this, v).printResult();
    }

    /** * Export access method */
    public void setShortestPathStrategy(ShortestPathStrategy shortestPathStrategy) {
        this.shortestPathStrategy = shortestPathStrategy;
    }

    public List<Vertex> getVertexs() {
        return vertexs;
    }

    public int[][] getEdges() {
        return edges;
    }
}
算法接口设计
  • ShortestPathStrategy.java
package zychaowill.datastructure.graph.algo;

import zychaowill.datastructure.graph.vo.Graph;
import zychaowill.datastructure.graph.vo.Vertex;

public interface ShortestPathStrategy {

    ShortestResult shortestPath(Graph graph, Vertex v);
}
  • 抽象层实现: AbstractShortestPathStrategy.java
package zychaowill.datastructure.graph.algo;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Queue;

import zychaowill.datastructure.graph.vo.Graph;
import zychaowill.datastructure.graph.vo.Vertex;

public abstract class AbstractShortestPathStrategy implements ShortestPathStrategy {

    protected final int MAX_VALUE = Integer.MAX_VALUE;
    protected List<Vertex> vertexs; // all vertexs of graph
    protected int[][] edges; // weight between two vertexs
    protected Queue<Vertex> S;
    protected Queue<Vertex> U;

    /** * get shortest path length * @see * @return */
    protected int getShortestPathLength() {
        int path = 0;
        List<Vertex> list = new ArrayList<>(S);
        for (int i = 1; i < list.size(); i++) {
            path += getDistance(list.get(i - 1), list.get(i));
        }

        return path;
    }

    /* * 获取顶点所有(未访问的)邻居 */
    protected List<Vertex> getNeighbors(Vertex v) {
        List<Vertex> neighbors = new ArrayList<>();
        int position = vertexs.indexOf(v);

        Vertex neighbor = null;
        int distance;
        for (int i = 0; i < vertexs.size(); i++) {
            if (i == position) {
                continue;
            }

            distance = edges[position][i];
            if (distance < MAX_VALUE) {
                neighbor = vertexs.get(i);
                if (U.contains(neighbor)) {
                    neighbors.add(neighbor);
                }
            }
        }

        return neighbors;
    }

    /* * 获取顶点到目标顶点的距离 */
    protected int getDistance(Vertex source, Vertex destination) {
        int sourceIndex = vertexs.indexOf(source);
        int destinationIndex = vertexs.indexOf(destination);
        return edges[sourceIndex][destinationIndex];
    }

    /* * 更新所有邻居的最短路径 */
    protected void updateDistance(Vertex vertex, List<Vertex> neighbors) {
        for (Vertex neighbor : neighbors) {
            updateDistance(vertex, neighbor);
        }
    }

    /* * 更新邻居的最短路径 */
    protected void updateDistance(Vertex vertex, Vertex neighbor) {
        int distance = getDistance(vertex, neighbor) + vertex.getPath();
        if (distance < neighbor.getPath()) {
            neighbor.setPath(distance);
        }
    }

    /* * 根据顶点位置获取顶点 */
    protected Vertex getVertex(int index) {
        return vertexs.get(index);
    }

    /** * 初始化 */
    protected void init(Graph graph, Vertex v) {
        this.vertexs = graph.getVertexs();
        this.edges = graph.getEdges();

        initUnVisited();

        S = new LinkedList<>();
    }

    /** * 初始化未访问顶点集合 * @see */
    private void initUnVisited() {
        U = new PriorityQueue<>();
        for (Vertex v : vertexs) {
            U.add(v);
        }
    }
}
  • 结果集构建: ShortestResult.java
package zychaowill.datastructure.graph.algo;

import java.util.Queue;

import zychaowill.datastructure.graph.vo.Vertex;

public class ShortestResult {

    Queue<Vertex> vertexs;
    int path;

    public ShortestResult(Queue<Vertex> vertexs, int path) {
        this.vertexs = vertexs;
        this.path = path;
    }

    public void printResult() {
        final String separator = " -> ";
        StringBuilder builder = new StringBuilder("");

        while (!vertexs.isEmpty()) {
            builder.append(vertexs.poll().getName() + separator);
        }

        String shortestPath = builder.substring(0, builder.lastIndexOf(separator));
        System.out.println(shortestPath + ", length: " + path);
    }
}
Dijkstra算法实现
  • Dijkstra.java
package zychaowill.datastructure.graph.algo.impl;

import java.util.List;

import zychaowill.datastructure.graph.algo.AbstractShortestPathStrategy;
import zychaowill.datastructure.graph.algo.ShortestResult;
import zychaowill.datastructure.graph.vo.Graph;
import zychaowill.datastructure.graph.vo.Vertex;

public class Dijkstra extends AbstractShortestPathStrategy {

    @Override
    public ShortestResult shortestPath(Graph graph, Vertex v) {
        init(graph, v);

        Vertex w;
        while (!U.isEmpty()) {
            w = U.element();
            List<Vertex> neighbors = getNeighbors(w);
            updateDistance(w, neighbors);
            S.add(U.poll());
        }

        return new ShortestResult(S, getShortestPathLength());
    }
}
算法测试
  • ShortestPath.java
package zychaowill.datastructure.graph.examples;

import java.util.ArrayList;
import java.util.List;

import zychaowill.datastructure.graph.algo.impl.Dijkstra;
import zychaowill.datastructure.graph.vo.Graph;
import zychaowill.datastructure.graph.vo.Vertex;

public class DijkstraShortestPath {

    public static void main(String[] args) {
        List<Vertex> vertexs = new ArrayList<Vertex>();
        Vertex a = new Vertex("0", 0);
        Vertex b = new Vertex("1");
        Vertex c = new Vertex("2");
        Vertex d = new Vertex("3");
        Vertex e = new Vertex("4");
        Vertex f = new Vertex("5");
        Vertex g = new Vertex("6");
        vertexs.add(a);
        vertexs.add(b);
        vertexs.add(c);
        vertexs.add(d);
        vertexs.add(e);
        vertexs.add(f);
        vertexs.add(g);
        int[][] edges = { { 0, 4, 6, 6, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE },
                { Integer.MAX_VALUE, 0, 1, Integer.MAX_VALUE, 7, Integer.MAX_VALUE, Integer.MAX_VALUE },
                { Integer.MAX_VALUE, Integer.MAX_VALUE, 0, 2, 6, 4, Integer.MAX_VALUE },
                { Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, 0, Integer.MAX_VALUE, 5, Integer.MAX_VALUE },
                { Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, 0, Integer.MAX_VALUE, 6 },
                { Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, 1, 0, 8 },
                { Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE }
        };

        Graph graph = new Graph(vertexs, edges);
        graph.setShortestPathStrategy(new Dijkstra());
        graph.getShortestPath(a);
    }
}
测试结果:

《【连载】Dijkstra求最短路径算法设计—Java实现》

好了,到此就完整实现了Dijkstra求最短路径算法。如果需要代码的话,可以到我的Github仓库下载

    原文作者:Dijkstra算法
    原文地址: https://blog.csdn.net/qq_17776287/article/details/78597665
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞