0
点赞
收藏
分享

微信扫一扫

Dijkstra算法

夏天的枫_ 2022-02-10 阅读 74

求点A到点E的最短距离

package com.byc.day2;

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

public class DijkstraAlgorithm {

    public static void main(String[] args) {
        //1、所有的顶点
        char[] vertex = {'A','B','C','D','E','F','G'};


        // 2、邻接矩阵
        int[][] matrix = new int[vertex.length][vertex.length];
        final int N = 65535;// 表示不可连接
        matrix[0] = new int[]{N,5,7,N,N,N,2};
        matrix[1] = new int[]{5,N,N,9,N,N,3};
        matrix[2] = new int[]{7,N,N,N,8,N,N};
        matrix[3] = new int[]{N,9,N,N,N,4,N};
        matrix[4] = new int[]{N,N,8,N,N,5,4};
        matrix[5] = new int[]{N,N,N,4,5,N,6};
        matrix[6] = new int[]{2,3,N,N,4,6,N};
        // 3、创建 Graph 对象
        Graph graph = new Graph(vertex, matrix);
        // 4、测试,看看图的邻接矩阵是否ok
        graph.showGraph();
        // 5、计算出所有顶点到 0 的最短距离和前驱结点
        graph.dsj(graph.vertexList.indexOf('A'));
        // 6、获得 0 -> 5 号结点的最短距离
        int dis = graph.vv.getDis(graph.vertexList.indexOf('E'));
        System.out.println(dis);
        // 7、打印最短路径从 0 -> 5 的经过的所有的点
        graph.printVisit(graph.vertexList.indexOf('E'));
    }


}


class Graph{

    private char[] vertex; //顶点数组
    private int[][] matrix; //邻接矩阵
    public VisitedVertx vv;
    public List<Character> vertexList;
    private final int N = 65535;

    // 构造器
    public Graph(char[] vertex, int[][] matrix) {
        this.vertex = vertex;
        this.matrix = matrix;
        vertexList = getList(vertex);
    }

    // 显示图
    public void showGraph(){
        for (int[] link : matrix) {
            System.out.println(Arrays.toString(link));
        }
    }

    // 迪杰斯特拉算法的实现
    public void dsj(int startIndex){
        vv = new VisitedVertx(vertex.length, startIndex);
        int[] alreadyArr = vv.alreadyArr;

        int now = startIndex;

        while (true){
            int[] nowCanArrive = this.matrix[now];
            for (int i = 0; i < nowCanArrive.length; i++) {
                if (alreadyArr[i]==1){
                    continue;
                }
                int newDis = vv.getDis(now) + nowCanArrive[i];
                if (vv.getDis(i)==N && nowCanArrive[i]!=N) {
                    vv.updateDis(i,newDis);
                    vv.updatePre(i,now);
                } else if (vv.getDis(i)!=N && nowCanArrive[i]!=N){
                    if (newDis < vv.getDis(i)) {
                        vv.updateDis(i,newDis);
                        vv.updatePre(i,now);
                    }
                }
            }

            int minIndex = -1;
            int minDis = N;
            for (int i1 = 0; i1 < alreadyArr.length; i1++) {
                if (alreadyArr[i1]==1){
                    continue;
                }
                int dis = vv.getDis(i1);
                if (dis < minDis){
                    minIndex = i1;
                    minDis = dis;
                }
            }

            if (minIndex == -1){
                break;
            }
            alreadyArr[minIndex] = 1;
            now = minIndex;

        }

        System.out.println();
    }

    public void printVisit(int index){
        if (vv.preVisited[index]==index){
            System.out.print(vertexList.get(index) + "\t");
        } else {
            printVisit(vv.preVisited[index]);
            System.out.print(vertexList.get(index) + "\t");
        }
    }

    private static List<Character> getList(char[] vertex) {
        List<Character> characters = new ArrayList<>();
        for (char c : vertex) {
            characters.add(c);
        }
        return characters;
    }

}

// 已访问顶点的集合
class VisitedVertx{
    // 记录各个顶点是否访问过 1表示已经ok,0会动态更新
    public int[] alreadyArr;
    // 每个下标对应的值为第一个顶点的下标,会动态更新
    public int[] preVisited;
    // 记录出发顶点到其他所有点的距离,例如G为出发点,就会记录G到其他顶点的距离,会动态更新,求的最短距离就会存放到dis
    public int[] dis;

    public VisitedVertx(int length, int index) {
        this.alreadyArr = new int[length];
        this.preVisited = new int[length];
        this.dis = new int[length];
        //初始化dis数组
        Arrays.fill(dis,65535);
        this.dis[index] = 0;
        this.preVisited[index] = index;
        this.alreadyArr[index] = 1;
    }

    /**
     * 判断该顶点是否被访问过
     * 如果被访问过,就返回true,否则返回false
     */
    public boolean in(int index){
        return alreadyArr[index] == 1;
    }

    /**
     * 更新从出发点到顶点index的距离
     */
    public void updateDis(int index, int len){
        dis[index] = len;
    }


    /**
     * 更新顶点为前驱index顶点
     */
    public void updatePre(int pre,int index){
        preVisited[pre] = index;
    }

    /**
     * 功能:返回出发点到index点的距离
     */
    public int getDis(int index){
        return dis[index];
    }


}

举报

相关推荐

0 条评论