迪杰斯特拉算法(计算路径)

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);
    }
}

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

原文地址:https://www.cnblogs.com/rao11/p/12024402.html

时间: 2024-10-09 19:00:01

迪杰斯特拉算法(计算路径)的相关文章

迪杰斯特拉算法——PAT 1003

本文主要是将我对于我对于迪杰斯特拉算法的理解写出来,同时通过例题来希望能够加深对于算法的理解,其中有错误的地方希望大家指正. 迪杰斯特拉算法 我将这个算法理解成一个局部到整体的算法,这个方法确实越研究就会发现越经典. 首先可以将整个图的节点看成两个集合:一个是S,一个是U-S.如果是求v0到图中各点的最短距离的话,那么S就是已经确认到v0距离最短的点,U-S则是对于整体的点集合U,还没有加入S集合的点. 这里提出一个算法总体的思想,将所有的点按照一定的原则加入到S集就是解集.而这个解法就是重点了

迪杰斯特拉算法介绍

迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径. 它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止. 基本思想 通过Dijkstra计算图G中的最短路径时,需要指定起点s(即从顶点s开始计算). 此外,引进两个集合S和U.S的作用是记录已求出最短路径的顶点(以及相应的最短路径长度),而U则是记录还未求出最短路径的顶点(以及该顶点到起点s的距离). 初始时,S中只有起点s:U中是除s之外的顶点,并且U中顶点的路径是"起点s

图(最短路径算法————迪杰斯特拉算法和弗洛伊德算法).RP

文转:http://blog.csdn.net/zxq2574043697/article/details/9451887 一: 最短路径算法 1. 迪杰斯特拉算法 2. 弗洛伊德算法 二: 1. 迪杰斯特拉算法 求从源点到其余各点的最短路径 依最短路径的长度递增的次序求得各条路径 路径长度最短的最短路径的特点: 在这条路径上,必定只含一条弧,并且这条弧的权值最小. 下一条路径长度次短的最短路径的特点: 它只可能有两种情况:或是直接从源点到该点(只含一条弧):或者是从源点经过顶点v1,再到达该顶

十大基础实用算法之迪杰斯特拉算法、最小生成树和搜索算法

迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径. 它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止. 基本思想 通过Dijkstra计算图G中的最短路径时,需要指定起点s(即从顶点s开始计算). 此外,引进两个集合S和U.S的作用是记录已求出最短路径的顶点(以及相应的最短路径长度),而U则是记录还未求出最短路径的顶点(以及该顶点到起点s的距离). 初始时,S中只有起点s:U中是除s之外的顶点,并且U中顶点的路径是"起点s

普里姆算法,克鲁斯卡尔算法,迪杰斯特拉算法,弗洛里德算法

做数据结构的课程设计顺便总结一下这四大算法,本人小白学生一枚, 如果总结的有什么错误,希望能够告知指正 普里姆算法如图所示prim 找出最短的边,再以这条边构成的整体去寻找与之相邻的边,直至连接所有顶点,生成最小生成树,时间复杂度为O(n2) 克鲁斯卡尔算法如图所示kruskal 克鲁斯卡尔算法,假设连通网N=(N,{E}),则令最小生成树的初始状态为只有n个顶点而无边的非连通图T=(V,{}),图中每个顶点 自成一个连通分量.在E中选择代价最小的边,若该边依附的定顶点落在T中不同的连通分量上,

数据结构图之三(最短路径--迪杰斯特拉算法——转载自i=i++

数据结构图之三(最短路径--迪杰斯特拉算法) [1]最短路径 最短路径?别乱想哈,其实就是字面意思,一个带边值的图中从某一个顶点到另外一个顶点的最短路径. 官方定义:对于内网图而言,最短路径是指两顶点之间经过的边上权值之和最小的路径. 并且我们称路径上的第一个顶点为源点,最后一个顶点为终点. 由于非内网图没有边上的权值,所谓的最短路径其实是指两顶点之间经过的边数最少的路径. 别废话了!整点实际的哈,你能很快计算出下图中由源点V0到终点V8的最短路径吗? [2]迪杰斯特拉算法 迪杰斯特拉算法是按路

【其它】LJX的迪杰斯特拉算法报告

迪杰斯特拉(di jie qi)算法 这里有一张图: 假设要求从1号节点到5号节点的最短路.那么根据迪杰斯特拉算法的思想,我们先看: 节点1,从节点1出发的一共有3条路,分别是1-6.1-3.1-2.然后我们分别看每条路的权值,发现1-6的权值为14,记录下来.1-3的权值为9,记录下来.1-2的权值为7,记录下来.我们发现好像不能再从1号节点发现什么了,所以,我们把它out掉. 接着按顺序看2号节点,从节点2发出了2条路分别是2-3与2-4,我们接着向计算1号节点一样计算2号节点.先计算2-3

[小明学算法]4.Dijkstra(迪杰斯特拉)算法

1.定义概念 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.值得注意的是,该算法要求图中不存在负权边. 2.基本思想 设置顶点集合S,初始时,S中仅含有起始点,把从起始点到u且中间只经过S中顶点的路称为从起始点到u的特殊路径,并用数组dist记录当前每个顶点所对应的最短特殊路径的长度.Dijkstra算法每次从S外取出对应dist值最小的节点u,将其添加到S中,并对所有与u点直接相连

用迪杰斯特拉算法实现地铁的站点搜索

上一篇文章,利用迪杰斯特拉(dijkstra)算法,实现了无向图的最短路径搜索功能.本篇将以南京地铁为例,用迪杰斯特拉算法实现两个站点之间的最短路径搜索. 借用百度百科,南京2015年4月份的地铁运行线路图如下: 创建一个数据构造类,初始化南京地铁的各条线路站点数据(截至2015年4月南京地铁运营公司数据,与上图对应) /** * */ package com.test.dijkstra; import java.util.ArrayList; import java.util.HashSet;