图的最短路径和拓扑排序

图的最短路径

从某顶点出发,沿图的边到达另一顶点所经过的路径中,各边上权值之和最小的一条路径叫做最短路径

图的最短路径有许多重要的应用。

例如:上图中v0-v8有9个点,可以看做不同的地点,现在要规划出v0到其它某个点地点的最短路线规划

构建最短路径中比较常见的一种算法即为dijstra(迪杰斯特拉)算法

二、dijstra(迪杰斯特拉)算法

究竟什么是迪杰斯特拉算法?它是如何寻找图中顶点的最短路径呢?

这个算法的本质,是不断刷新起点与其他各个顶点之间的 “距离表”。

让我们来演示一下迪杰斯特拉的详细过程:

第1步,创建距离表。表中的Key是顶点名称,Value是从起点A到对应顶点的已知最短距离。但是,一开始我们并不知道A到其他顶点的最短距离是多少,Value默认是无限大:

第2步,遍历起点A,找到起点A的邻接顶点B和C。从A到B的距离是5,从A到C的距离是2。把这一信息刷新到距离表当中:

第3步,从距离表中找到从A出发距离最短的点,也就是顶点C。

第4步,遍历顶点C,找到顶点C的邻接顶点D和F(A已经遍历过,不需要考虑)。从C到D的距离是6,所以A到D的距离是2+6=8;从C到F的距离是8,所以从A到F的距离是2+8=10。把这一信息刷新到表中:

接下来重复第3步、第4步所做的操作:

第5步,也就是第3步的重复,从距离表中找到从A出发距离最短的点(C已经遍历过,不需要考虑),也就是顶点B。

第6步,也就是第4步的重复,遍历顶点B,找到顶点B的邻接顶点D和E(A已经遍历过,不需要考虑)。从B到D的距离是1,所以A到D的距离是5+1=6,小于距离表中的8;从B到E的距离是6,所以从A到E的距离是5+6=11。把这一信息刷新到表中:

(在第6步,A到D的距离从8刷新到6,可以看出距离表所发挥的作用。距离表通过迭代刷新,用新路径长度取代旧路径长度,最终可以得到从起点到其他顶点的最短距离)

第7步,从距离表中找到从A出发距离最短的点(B和C不用考虑),也就是顶点D。

第8步,遍历顶点D,找到顶点D的邻接顶点E和F。从D到E的距离是1,所以A到E的距离是6+1=7,小于距离表中的11;从D到F的距离是2,所以从A到F的距离是6+2=8,小于距离表中的10。把这一信息刷新到表中:

第9步,从距离表中找到从A出发距离最短的点,也就是顶点E。

第10步,遍历顶点E,找到顶点E的邻接顶点G。从E到G的距离是7,所以A到G的距离是7+7=14。把这一信息刷新到表中:

第11步,从距离表中找到从A出发距离最短的点,也就是顶点F。

第10步,遍历顶点F,找到顶点F的邻接顶点G。从F到G的距离是3,所以A到G的距离是8+3=11,小于距离表中的14。把这一信息刷新到表中:

就这样,除终点以外的全部顶点都已经遍历完毕,距离表中存储的是从起点A到所有顶点的最短距离。显然,从A到G的最短距离是11。(路径:A-B-D-F-G)

代码实现:

package cn.itcast.grape;

import cn.itcast.treeandgrape.Graph;

public class JavaDijstra {
    private final static int MAXVEX = 9;//顶点,以后不需要写死
    private final static int MAXWEING = 65535;//(最大)权重
    private int shortTablePath[] = new int[MAXVEX];//存储V0到某顶点最短路径的权值和 例:{0,1,5}

    /**
     * 获取一个图的最短路径
     */
    public void shortestPathDijstra(Graph graph) {
        int min;//最小值
        int k = 0;//记录下标
        boolean isgetPath[] = new boolean[MAXVEX];//是否已经拿到了V0到Vm的最短路径

        for (int v = 0; v < graph.getVertexSize(); v++) {//遍历顶点数量
            shortTablePath[v] = graph.getMatrix()[0][v];//获得V0这一行的权值数组
        }
        shortTablePath[0] = 0;//V0到V0的距离是0, 拿到数据后,不必往回走
        isgetPath[0] = true;
        for (int v = 1; v < graph.getVertexSize(); v++) {//横向
            min = MAXWEING;//初始化
            for (int w = 0; w < graph.getVertexSize(); w++) {//纵向,对找出来的顶点一个一个遍历
                if (!isgetPath[w] && shortTablePath[w] < min) {
                    k = w;
                    min = shortTablePath[w];
                }
            }
            isgetPath[k] = true;
            for (int j = 0; j < graph.getVertexSize(); j++) {
                if (!isgetPath[j] && (min + graph.getMatrix()[k][j] < shortTablePath[j])) {
                    shortTablePath[j] = min + graph.getMatrix()[k][j];
                }
            }
        }
        for (int i = 0; i < shortTablePath.length; i++) {
            System.out.println("V0到V" + i + "的最短路径为:" + shortTablePath[i] + "\n");
        }
    }

    public static void main(String[] args) {
        Graph graph = new Graph(MAXVEX);
        graph.createGraph();
        JavaDijstra dijstra = new JavaDijstra();
        dijstra.shortestPathDijstra(graph);
    }
}

原文地址:https://www.cnblogs.com/xiaozhongfeixiang/p/11725665.html

时间: 2024-08-29 03:29:30

图的最短路径和拓扑排序的相关文章

图的遍历:拓扑排序

[需要解决的问题] 对一个有向无环图(DAG)拓扑排序. 拓扑排序就是,对图上的点进行排序,使得排在后面的点不能通过一条路径到前面的点. 比如下面这个图: 其中一个拓扑排序是1,2,3,4,5:而1,2,5,3,4就不行,因为3能到达5. 因此可以得出: 用一个队列实现,先把入度为0的点放入队列,每次将队首元素加入ans[i-j]中,删除队首元素,并删除该点连接的所有边,于是每次删除一个点都会产生一个新的入度为0的点,再把这个点插入队列,递归即可. 拓扑排序 模板如下: //复杂度:O(N+M)

数据结构学习笔记(十)-图的最小生成树与拓扑排序

一.最小生成树 首先应该理解最小生成树的定义: 包含图的所有顶点,V-1条边 没有回路 边的权重和最小 那么实际问题中用到最小生成树是什么时候呢?很多人都觉得学习算法没用,在实际生活工作中根本就用不上,其实并不是用不上,只是你根本没有想到要去用而已!使用了算法后你就会发现事情原来可以这么简单高效! 实际中如需要使用最少的电线给一栋房子安装电路.就可以用最小生成树解决. 1. Prim算法 该算法利用了贪心的思想,大体上与dijkstra算法类似,都需要对每一个顶点保存一个距离值dv和pv,以及一

数据结构--图(下)--拓扑排序

拓扑排序 思维导图也是图的一种 拓扑序:如果图中从V到W有一条有向路径,则V一定排在W之前.满足此条件的顶点排序成为一个拓扑序.  V->W 获得一个拓扑序的过程就是拓扑排序 AOV如果有合理的拓扑序,则必定是有向无环图(Directed Acyclic Graph,简称DAG). 第一排没有预修课程的课.然后抹掉顶点和边, 每一次输出哪个顶点呢,没有前驱顶点,就输出(入度为0的顶点). 最后的拓扑序就产生了 DAG有向无环图. 拓扑排序的应用 AOE(Activity On Edge)网络  

bzoj5017 [Snoi2017]炸弹 (线段树优化建图+)tarjan 缩点+拓扑排序

题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=5017 题解 这个题目方法挺多的. 线段树优化建图 线段树优化建图的做法应该挺显然的,一个炸弹能够引爆的炸弹的显然应该是一个区间里面的,直接对这个区间进行线段树优化建图. 这样可以得到一个带环图,缩点以后这个炸弹能够炸到的炸弹就是从这个点能够走到的点. 但是这个不太好做,不过可以发现最终的炸弹也是一个区间,所以可以通过缩点后的 DAG 来求出左右端点. 时间复杂度 \(O(n\log n)\)

[HAOI2012] 道路 - 最短路图,拓扑排序,dp

给定一个无向图,一条路径被称为最短路,当且仅当不存在从它的起点到终点的另外一条路径总长度比它小.两条最短路不同,当且仅当它们包含的道路序列不同.我们需要对每条道路的重要性进行评估,评估方式为计算有多少条不同的最短路经过该道路.\(n\leq 1500,m\leq 5000,w\leq 10000\) Solution 枚举每个点作为起点,跑出最短路径图,对其拓扑排序后,DP 统计出每个点发出和从起点到达该点的最短路的总数,然后扫一遍所有边统计答案即可. 注意可能有重边 #include <bit

7-9-有向图无环拓扑排序-图-第7章-《数据结构》课本源码-严蔚敏吴伟民版

课本源码部分 第7章  图 - 有向无环图拓扑排序 ——<数据结构>-严蔚敏.吴伟民版        源码使用说明  链接??? <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明        课本源码合辑  链接??? <数据结构>课本源码合辑        习题集全解析  链接??? <数据结构题集>习题解析合辑        本源码引入的文件  链接? Status.h.SequenceStack.c.ALGraph.c    

【图】拓扑排序

参考CSDN拓扑排序的原理及Java实现 拓扑排序C++实现 拓扑排序百度百科 若不是上了学堂在线的数据结构课程,我估计今后不做技术的话,都接触不到图的拓扑排序这个概念了.先是看了百度百科的解释,拓扑排序现实中的应用是选课,即某些课程需要一些先修课程的学习后才适合上.比如数据结构的学习,是离散数学.编程语言,后者是前者的先修课程. 拓扑排序定义:将有向无环图DAG中的顶点以线性方式进行排序.即对于任何连接自顶点u到顶点v的有向边uv,在最后的排序结果中,顶点u总是在顶点v的前面. 1.创建图:

数据结构-图的应用-拓扑排序

一.基础知识 1.AOV-网 (Activity On Vertex Network):用顶点表示活动,用弧表示活动之间的优先关系的有向无环图. 2.AOE-网 (Activity On Edge Network):用顶点表示事件,用边表示活动,带权的有向无环图. 3.拓扑排序:将AOV-网中所有顶点排成一个线性序列(顶点  到  顶点有一条路径,则该线性序列中  一定在  之前) 二.拓扑排序算法思想 1.在AOV-网中选取一个无前驱的顶点,并输出 2.从图中删除所有该顶点发出的有向边 3.重

数据结构实践项目——最短路径和拓扑序列

本文是针对[数据结构基础系列(7):图]的第2组实践例程. (程序中graph.h是图存储结构的"算法库"中的头文件,详情请单击链接-) 0710 生成树的概念 0711 最小生成树的普里姆算法 0712 最小生成树的克鲁斯卡尔算法 0713 从一个顶点到其余各顶点的最短路径 0714 每对顶点之间的最短路径 0715 拓扑排序 0716 AOE网与关键路径 纸上谈兵:"知原理"检验题目 1.针对下面的图1: (图1) (1)写出图的邻接矩阵: (2)按照Prim算