zoukankan      html  css  js  c++  java
  • 迪杰斯特拉算法(计算路径)

    package com.rao.graph;
    
    
    import java.util.LinkedList;
    import java.util.List;
    
    /**
     * @author Srao
     * @className DijkstraWithPath
     * @date 2019/12/11 17:59
     * @package com.rao.graph
     * @Description 迪杰斯特拉算法(计算路径)
     */
    public class DijkstraWithPath {
    
        /**
         * 图的顶点
         */
        private static class Vertex{
            String data;
            public Vertex(String data) {
                this.data = data;
            }
        }
    
        /**
         * 图的边
         */
        private static class Edge{
            int index;
            int weight;
            public Edge(int index, int weight) {
                this.index = index;
                this.weight = weight;
            }
        }
    
        /**
         * 图(邻接矩阵)
         */
        private static class Graph{
            private Vertex[] vertices;
            private LinkedList<Edge>[] adj;
            Graph(int size){
                vertices = new Vertex[size];
                adj = new LinkedList[size];
                for (int i = 0; i < adj.length; i++) {
                    adj[i] = new LinkedList<>();
                }
            }
        }
    
        /**
         * 初始化图
         * @param graph
         */
        private static void initGraph(Graph graph){
            graph.vertices[0] = new Vertex("A");
            graph.vertices[1] = new Vertex("B");
            graph.vertices[2] = new Vertex("C");
            graph.vertices[3] = new Vertex("D");
            graph.vertices[4] = new Vertex("E");
            graph.vertices[5] = new Vertex("F");
            graph.vertices[6] = new Vertex("G");
    
            graph.adj[0].add(new Edge(1, 5));
            graph.adj[0].add(new Edge(2, 2));
            graph.adj[1].add(new Edge(0, 5));
            graph.adj[1].add(new Edge(3, 1));
            graph.adj[1].add(new Edge(4, 6));
            graph.adj[2].add(new Edge(0, 2));
            graph.adj[2].add(new Edge(3, 6));
            graph.adj[2].add(new Edge(5, 8));
            graph.adj[3].add(new Edge(1, 1));
            graph.adj[3].add(new Edge(2, 6));
            graph.adj[3].add(new Edge(4, 1));
            graph.adj[3].add(new Edge(5, 2));
            graph.adj[4].add(new Edge(1, 6));
            graph.adj[4].add(new Edge(3, 1));
            graph.adj[4].add(new Edge(6, 7));
            graph.adj[5].add(new Edge(2, 8));
            graph.adj[5].add(new Edge(3, 2));
            graph.adj[5].add(new Edge(6, 3));
            graph.adj[6].add(new Edge(4, 7));
            graph.adj[6].add(new Edge(5, 3));
        }
    
        /**
         * 迪杰斯特拉算法(计算路径)
         * @param graph:图
         * @param startIndex:起始顶点
         * @return 返回前置顶点表
         */
        public static int[] dijkstra(Graph graph, int startIndex){
            //图顶点的数量
            int size = graph.vertices.length;
            //创建距离表,存放每一个点到起始点的最小距离
            int[] distances = new int[size];
    
            //创建前置顶点表,存放每一个顶点到起始点的路径中,倒数第二个点的下标
            int[] prevs = new int[size];
    
            //记录每个顶点的遍历状态,true为已经访问过
            boolean[] access = new boolean[size];
    
            //初始化每一个点到起始点的距离为无穷大
            for (int i = 0; i < size; i++) {
                distances[i] = Integer.MAX_VALUE;
            }
    
            //初始化与初始点相连的点
            access[0] = true;
            List<Edge> edgesFromStart = graph.adj[startIndex];
            for (Edge edge : edgesFromStart) {
                distances[edge.index] = edge.weight;
                prevs[edge.index] = 0;
            }
    
            //开始循环遍历所有的点
            for (int i = 1; i < size; i++) {
                int minDistanceFromStart = Integer.MAX_VALUE;
                int minDistanceIndex = -1;
                for (int j = 1; j < size; j++) {
                    if (!access[j] && distances[j] < minDistanceFromStart){
                        minDistanceFromStart = distances[j];
                        minDistanceIndex = j;
                    }
                }
                if (minDistanceIndex == -1){
                    break;
                }
                access[minDistanceIndex] = true;
                for (Edge edge : graph.adj[minDistanceIndex]) {
                    if (access[edge.index]){
                        continue;
                    }
                    int weight = edge.weight;
                    int preDistance = distances[edge.index];
                    if (weight !=Integer.MAX_VALUE && (minDistanceFromStart + weight < preDistance)){
                        distances[edge.index] = minDistanceFromStart + weight;
                        prevs[edge.index] = minDistanceIndex;
                    }
                }
            }
    
            return prevs;
        }
    
        /**
         * 输出路径
         * @param vertices:图中的所有顶点
         * @param prev:前置顶点表
         * @param i:从后往前回溯,i的初始值是从起始点到要到达的顶点的下标
         */
        private static void printPrevs(Vertex[] vertices, int[] prev, int i){
            if (i > 0){
                printPrevs(vertices, prev, prev[i]);
            }
            System.out.println(vertices[i].data);
        }
    
        public static void main(String[] args) {
            Graph graph = new Graph(7);
            initGraph(graph);
            int[] prevs = dijkstra(graph, 0);
            printPrevs(graph.vertices, prevs, graph.vertices.length-1);
        }
    }

    利用递归前置顶点表的方法打印路径

  • 相关阅读:
    C#各版本新特性
    ubantu操作积累
    C# System.Net.Http.HttpClient使用说明
    IIS下VUE跳转
    融合主流的技术 分布式中间件+微服务+微架构架构
    论减少代码中return语句的骚操作
    shell脚本--多个代码库批量pull最新master代码
    SpringBoot单元测试
    Qt音视频开发36-USB摄像头解码qcamera方案
    Qt音视频开发35-Onvif图片参数
  • 原文地址:https://www.cnblogs.com/rao11/p/12024402.html
Copyright © 2011-2022 走看看