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

来源:互联网 发布:数据库 er设计 编辑:程序博客网 时间:2024/05/19 15:21

Dijkstra求最短路径算法设计

1. Dijkstra简介

  • What’s the shortest path?

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

  • Thought line of algorithm:

    这里写图片描述

  • How to realize Dijkstra algorithm:

    这里写图片描述

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求最短路径算法。如果需要代码的话,可以到我的Github仓库下载

原创粉丝点击