java实现迪杰斯特拉算法(dijkstra)-------参考视频 韩顺平《java数据结构和算法》

如图所示:
在这里插入图片描述
完整代码如下:

package com.wqc.dijkstra;

import java.util.Arrays;

/**
 * @author 高瞻远瞩
 * @version 1.0
 * @motto 算法并不可怕, 可怕的是你不敢面对它, 加油!别浮躁~冲击大厂!!!
 * 迪杰斯特拉算法  --》 最短路径问题(一个顶点到其他顶点的最短路径)
 * 问题描述:有七个村庄(A,B,C,D,E,F,G) 现在有6个邮差 从G点出发  分贝把邮件送到A,B,C,D,E,F 6个村庄
 * 问:如何计算出G村庄到其他各个村庄的最短距离
 */
public class DijkstraAlgorithm {
    public static void main(String[] args) {
        char[] vertexes = {'A', 'B', 'C', 'D', 'E', 'F', 'G' };
        int[][] matrix = new int[vertexes.length][vertexes.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};
        Graph graph = new Graph(vertexes, matrix);
        graph.print();
        graph.dijkstra(6);
        graph.show();
    }
}

class VisitedVertex {
    public int[] already_arr;//记录该索引的顶点是否已经被访问 0表示没有被访问  1表示被访问 动态更新
    public int[] pre_visited;//记录该索引对应的顶点的前驱结点的索引 初始化为0 动态更新
    public int[] dis;//记录出发顶点到其他所有顶点的距离 比如G为出发顶点,就会记录G到其他顶点的距离,
    //会动态更新  最后求的最短距离会被放在这个数组中 初始化的时候出发顶点到其他顶点的距离都默认为65535  到自己的距离为0

    /**
     * 构造器初始化以上三个数组
     *
     * @param index 出发点的索引
     * @param len   顶点数
     */
    public VisitedVertex(int index, int len) {
        already_arr = new int[len];
        already_arr[index] = 1;
        pre_visited = new int[len];
        dis = new int[len];
//        for (int i = 0; i < len; i++) {
//            dis[i] = 65535;
//        }
        Arrays.fill(dis, 65535);
        dis[index] = 0;
    }


    /**
     * 判断对应索引的结点是否已经被访问过
     *
     * @param index 索引
     * @return 如果被访问过 返回真  否则返回假
     */
    public boolean isVisited(int index) {
        return already_arr[index] == 1;
    }

    /**
     * 更新指定索引结点的索引为前驱结点的索引
     *
     * @param index 指定结点
     * @param pre   前驱结点
     */
    public void updatePre(int index, int pre) {
        pre_visited[index] = pre;
    }

    /**
     * 更新出发结点到其他结点的距离
     *
     * @param index 其他结点的距离
     * @param len   距离
     */
    public void updateDis(int index, int len) {
        dis[index] = len;
    }

    /**
     * 返回指定索引的结点到出发结点的距离
     *
     * @param index 指定索引
     * @return 返回出发结点到指定索引结点的距离
     */
    public int getDis(int index) {
        return dis[index];
    }

    /**
     * 获取到出发结点的下一个新的访问结点 原则上是离出发结点最近的且没有被访问的结点
     * 访问的顺序是G-->A(2)
     * G-->B(3)
     * G-->E(4)
     * G-->F(6)
     * G-->C(G-->A-->C 9)
     * G-->D(G->F->D 10)
     *
     * @param index 出发结点的索引
     */
    public int nextNoVisitedVertex(int index) {
        int min = 65535;
        int next = -1;
        for (int i = 0; i < dis.length; i++) {
            if (!isVisited(i) && dis[i] < min) { //第一次访问后 dis:{2,3,65535,65535,4,6,0}
                min = dis[i];
                next = i;
            }
        }
        already_arr[next] = 1;//标记为已访问
        return next;
    }

    @Override
    public String toString() {
        return "VisitedVertex{" +
                "already_arr=" + Arrays.toString(already_arr) +
                "\n pre_visited=" + Arrays.toString(pre_visited) +
                "\n dis=" + Arrays.toString(dis) +
                '}';
    }
}

class Graph {
    private char[] vertexes;//顶点数组
    public int[][] matrix;//邻接矩阵
    VisitedVertex visitedVertex;

    public Graph(char[] vertexes, int[][] matrix) {
        this.matrix = matrix;
        this.vertexes = vertexes;
    }

    //打印图
    public void print() {
        for (int[] link : matrix) {
            System.out.println(Arrays.toString(link));
        }
    }

    /**
     * 迪杰斯特拉算法的入口 从指定索引的结点出发
     *
     * @param index 指定索引
     */
    public void dijkstra(int index) {
        visitedVertex = new VisitedVertex(index, vertexes.length);
        update(index);
        for (int i = 1; i < vertexes.length; i++) { //已经有一个结点被访问  所以再循环vertexes.length - 1次
            index = visitedVertex.nextNoVisitedVertex(index);
            update(index);
        }
    }

    /**
     * 更新出发结点的所有后继节点 以及 出发结点到所有其他结点的距离
     *
     * @param index 出发结点的索引
     */
    private void update(int index) {
        for (int i = 0; i < matrix[index].length; i++) {
            //visitedVertex.getDis(index) 恒为0  因为初始化dis数组的时候  出发结点到其他结点的距离统一为65535 除了自己
            int len = visitedVertex.getDis(index) + matrix[index][i];//出发结点到index索引结点的距离 + index结点到i结点的距离
            if (!visitedVertex.isVisited(i) && len < visitedVertex.dis[i]) {//前提没有被访问 算出的距离还必须小于已有的距离
                visitedVertex.updatePre(i, index);//更新该索引结点的前驱结点为index这个索引(即出发顶点)
                visitedVertex.updateDis(i, len);//更新该索引的结点到出发结点点的距离
                if (visitedVertex.pre_visited[index] != 0) {
                    System.out.println(vertexes[visitedVertex.pre_visited[index]] + "-->" + vertexes[index] + "-->" + vertexes[i] + " len=" + len);
                }
            }
        }
        if (visitedVertex.pre_visited[index] != 0) {//排除出发点自己  因为出发点的前驱始终为0
            System.out.println("顶点" + vertexes[index] + "的前驱=" + vertexes[visitedVertex.pre_visited[index]]);
        }
    }

    public void show() {
        System.out.println(visitedVertex);//打印最后的数组  dis数组即为最终解
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值