一、单源最短路(Dijkstra算法)

基本思想

选定一个源点,按路径长度递增次序,逐步产生最短路径(贪心),直到此源点到其他各顶点的最短路径全部求出为止。

数据结构

带权有向图G=(V,E),V = 1,2,…,n,顶点1为源点。图的存储结构为带权矩阵C。
一维数组D[n]:D[i]表示从源点1到顶点i的当前最短路径长度,初始时,D[i] = C[1][i];
一维数组P[n]:P[i]表示源点1到顶点i的当前最短路径上,最后经过的顶点,初始时,P[i]=1(源点);
S[n]:存放源点和已生成的终点,其初态为只有一个源点1。

实现步骤

1、将V分成两个集合,S(到源点最短路径已经确定的点)和V-S。初始时,S中只有源点1
2、在V-S中选取一个顶点w,使D[w]最小,将w加入集合S中;
3、调整数组D、P,即取D[i]和D[i]+C[w][v]中的较小者;
4、重复2和3,直到S中包含V的所有顶点。

代码实现

typedef struct
{int n, e;int ver[MAX];int EdgeWeight[MAX][MAX];
}DirectedWeightGraph/*图*/;
int MinWeight(int D[], bool S[])/*找到到源点路径最短的顶点*/
{int temp = INT_MAX;int w = 2;for (int i = 2; i <= MAX; i++){if (!S[i] && D[i] < temp){temp = D[i];w = i;}}return w;
}
void Dijkstra(DirectedWeightGraph G, int D[MAX+1]/*表示从源点1到顶点i的最短路径长度*/, int P[MAX+1]/*表示源点1到顶点i的最短路径上最后经过的顶点*/, bool S[MAX+1])
{int i, w, v, sum;for (i = 1; i <= G.n; i++)/*初始化,各个顶点到源点最短为两点间距离*/{D[i] = G.EdgeWeight[1][i];}for (i = 1; i < G.n; i++)/*进行n-1次*/{w = MinWeight(D, S);/*找到当前到源点近的顶点*/S[w] = true;/*将此顶点放入已经确定源点最短路径的顶点的集合*/for (v = 2; v <= G.n; v++)/*更新现在剩下各点到源点的最短路径*/{if (S[v] != true){sum = D[w] + G.EdgeWeight[w][v];/**即比较更新前此点到源点最短路径D[v]和更新后D[w]+C[w][v]的大小*/if (sum < D[v]){D[v] = sum;P[v] = w;}}}}
}

举个生动而形象的栗子:

那么问题来了,如果要求所有顶点之间的最短路径,咋整?当然可以用n遍Dikstra,也有另一个赫赫有名的算法——floyd-warshall

二、全局最短路径——Floyd-Warshall 算法

基本思想

要求两个点之间的最短路径,那么,可能经过一些图中其他的点,会使两点间路径最短,接下来就是要不断地尝试在两点间加入其他点,使得路径变短。最终要求的最短路径就是在两点中尝试了插入n个点之后得到的最短路径。
例如:有点0、1、2、3,要求点2、3间的最短路径,先求出2、3间可以经过点0的最短路径,再求出2、3间可以经过点0、1的最短路径,此时的最短路径即为最终要求的最短路径。
注意,Floyd算法求的是整体最短路径,故每次加入一个点,都需要调整全局所有点之间的最短路径,方便之后的迭代,关于详细的步骤,下文会阐述,这张图是一个详细的例子,可以先看看,看不懂没关系,可以看完后面我对迭代方程的详细解释后再来通过这张图练习一下,强化对算法的理解。

迭代方程如下:
D−1D_{-1}D−1​[i][j] = C[i][j]
DkD_kDk​[i][j] = min{Dk−1D_{k-1}Dk−1​[i][j],Dk−1D_{k-1}Dk−1​[i][k] + Dk−1D_{k-1}Dk−1​[k][j]}
其中DkD_kDk​表示两点间此时的最短路径长度,且经过的点的序号最大为k。
由此迭代方程,我们可以先求出每两个点之间只会经过点0的最短路径,再迭代得到每两个点之间只经过0、1的最短路径……得到每两个点之间经过的点的序号不大于k的最短路径,若共有n个点,直到得到每两个点之间经过的点的序号不大于n-1的最短路径,即为结果。

数据结构

带权的n有向图采用邻接矩阵C[n][n]存储
数组D[n][n]:存放在迭代过程中求得的最短路径长度
数组P[n][n]:存放路径

实现步骤

1、初始化,A[i][j] = C[i][j];
2、k从0开始到n,对于每个k求出每两个点i、j之间的最短路径,调整方法就是利用上述的迭代方程;

代码实现

void Floyd(int D[][MAX], int C[][MAX], int P[][MAX]/**存放最短路径*/, int n)
{int i, j, k;for (i = 0; i < n; i++)for (j = 0; j < n; j++){D[i][j] = C[i][j];P[i][j] = -1;}for (k = 0; k < n; k++)for (i = 0; i < n; i++)for (j = 0; j < n; j++)if (D[i][j] > D[i][k] + D[k][j]){D[i][j] = D[i][k] + D[k][j];P[i][j] = k;}
}

应用

很奇怪对不对,难道不是求出需要的两点间的最短路径就行了吗?为什么非要求出所有点之间的最短路径?
这个情况下就需要用到了:
一所未来会成为世界一流学校正在建,规划了几块地用来放教学楼啊、图书馆啊、宿舍啊、食堂啊等等。有的学生可能大学四年都不会去图书馆对不对,但是他总得去食堂吃饭啊,食堂肯定是每个人都要去的地方,那么食堂放在哪里呢?这时候选址的标准是什么?这时候就不需要哪一个建筑离食堂最近,而是需要离食堂最远的那个建筑不要离的太远。
可以让每个人都走15分钟到食堂,但不能让A同学下楼就到食堂了,B同学走一个小时才到食堂对不对。这时候求全局最短路径就派上用场了,对于每个点都知道了其他点到它的距离,比较一下每个点到其他点最远的距离即可。

随时评论区讨论

图的最短路算法(Dijkstra和Floyd-Warshall)相关推荐

  1. spfa算法_10行实现最短路算法——Dijkstra

    今天是算法数据结构专题的第34篇文章,我们来继续聊聊最短路算法. 在上一篇文章当中我们讲解了bellman-ford算法和spfa算法,其中spfa算法是我个人比较常用的算法,比赛当中几乎没有用过其他 ...

  2. zuc算法代码详解_最短路算法-dijkstra代码与案例详解

    引言 在研究路径选择和流量分配等交通问题时,常常会用到最短路算法.用最短路算法解决交通问题存在两个难点: 一.算法的选择和程序的编写.最短路算法有很多种改进算法和启发式算法,这些算法的效率不同,适用的 ...

  3. 单源(多源)最短路算法Dijkstra、Bellman-Ford、SPFA

    最短路算法 单源最短路:即一个点到任意点的最短路径 多源最短路:即任意一点到任意一点的最短路径 Dijkstra算法: 这个算法是通过点去更新最短路,每次找离源点最近的一个顶点,然后以该顶点为中心进行 ...

  4. 两种最短路径(测地距离)的算法——Dijkstra和Floyd

    从某顶点出发,沿图的边到达另一顶点所经过的路径中,各边上权值之和最小的一条路径叫做最短路径.解决最短路的问题有以下算法,Dijkstra算法,Bellman-Ford算法,Floyd算法和SPFA算法 ...

  5. 最短路径算法——Dijkstra and Floyd算法

    一.     前言:     这个古老的算法应该耳熟能详了吧,但是我自从从学校出来到现在,最短路径算法都没有实际运用过,最近在一个GIS项目中总算用到了,于是乎把教材重温了下,同时查阅了网上很多的资料 ...

  6. 指定起终点的最短路算法-Dijkstra标号法及其改进

    源代码来源于司守奎老师<数学建模与算法>,本人加了一些注释供大家参考: function [mydistance,mypath]=mydijkstra(a,sb,db); % 输入:a-邻 ...

  7. C++floyd warshall算法求最短路径(附完整源码)

    C++floyd warshall算法求最短路径 floyd warshall算法求最短路径的完整源码(定义,实现,main函数测试) floyd warshall算法求最短路径的完整源码(定义,实现 ...

  8. dijkstra算法_Python实现图的经典DFS、BFS、Dijkstra、Floyd、Prim、Kruskal算法

    讲在前面的话,图的算法太多,理论知识肯定一篇文章讲不完,关于理论知识大家可以参考教材Sedgewick的<算法>或reference的链接,本文主要还是想在一篇文章中记录六种算法的Pyth ...

  9. dfs时间复杂度_Python实现图的经典DFS、BFS、Dijkstra、Floyd、Prim、Kruskal算法

    讲在前面的话,图的算法太多,理论知识肯定一篇文章讲不完,关于理论知识大家可以参考教材Sedgewick的<算法>或reference的链接,本文主要还是想在一篇文章中记录六种算法的Pyth ...

最新文章

  1. ARM 位置无关代码(PIC)的分析理解
  2. 德鲁克的17条思想精髓,读懂管理的本质
  3. 走过路过不要错过,面了六轮才拿到阿里Android研发岗的Offer,确定不来看看?
  4. 形式参数内存在哪java_深入浅出Java中JVM内存管理
  5. OpenGL Shadow Mapping阴影贴图的实例
  6. 解决freeswitch ICE 获取RTP地址时间过长的问题
  7. [Node.js] 模块化 -- 爬虫
  8. 构建springmvc+dubbo分布式平台-dubbo简介
  9. VMware vCenter Server安装
  10. 不可逆加密算法有哪些_对称加密算法和非对称加密算法
  11. Android11.0 V-A/B无缝OTA升级update_engine
  12. SpringBoot实现导入功能
  13. 基于单片机的指纹密码锁系统
  14. Python 寻找完美数
  15. 【linux学习笔记】Linux网络管理综合项目实训任务书
  16. 分销商城系统模块_分销商城系统模块需求分析_OctShop
  17. C语言-编写函数isprime(int a),用来判断自变量a是否为素数。若是素数,函数返回整数1,否则返回0。
  18. extends和implement的区别
  19. 元宇宙与泛娱乐的邂逅:次世代第一CP养成记
  20. 阿里、京东、亚马逊为何如此重视重构“会员”?

热门文章

  1. 计算沙盒下文件夹内容大小 清空沙盒 文件 目录
  2. java Unicode转UTF-8代码
  3. 用bat文件在web端拉起本地cs应用(以拉起本地QQ音乐为例)
  4. H3C进入目录---用户视图
  5. java线程day-01
  6. JavaBean在jsp中的使用
  7. Excel 二次开发系列(3): 创建Excel二次开发环境
  8. 城市管网 GIS 数据表的存储
  9. 博客园,我的技术摇篮
  10. 【Spring 持久层】Spring 与 Mybatis 整合