一、算法介绍

  迪杰斯特拉算法(英语:Dijkstra's algorithm)由荷兰计算机科学家艾兹赫尔·迪杰斯特拉在1956年提出。迪杰斯特拉算法使用了广度优先搜索解决赋权有向图的单源最短路径问题。这个算法是通过为每个顶点 v 保留当前为止所找到的从s到v的最短路径来工作的。

  初始时,原点 src 的路径权重被赋为 0 (dist[src] = 0)。若对于顶点 m 存在能直接到达的边(src, m),则把d[m]设为w(src, m),同时把所有其他(src不能直接到达的)顶点的路径长度设为无穷大,即表示我们不知道任何通向这些顶点的路径(对于所有顶点的集合 V 中的任意顶点 v, 若 v 不为 src 和上述 m 之一, dist[v] = ∞)。当算法结束时,dist[v] 中存储的便是从 src 到 v 的最短路径,或者如果路径不存在的话是无穷大。

  边的拓展是 Dijkstra 算法的基础操作:如果存在一条从 u 到 v 的边,那么从 src 到 v 的最短路径可以通过将边(uv)添加到从 src 到 u 的路径尾部来拓展一条从 src 到 v 的路径。这条路径的长度是 dist[u] + w(u, v)。如果这个值比当前已知的 dist[v] 的值要小,我们可以用新的最小值来替代当前 dist[v] 中的值。拓展边的操作一直运行到所有的 dist[v] 都代表从 src 到 v 的最短路径的长度值。此算法的组织令 dist[u] 达到其最终值时,每条边(uv)都只被拓展一次。

二、Dijkstra算法步骤

  以下是 Dijkstra 算法中用于查找从单个源顶点到给定图中所有其他顶点的最短路径的详细步骤。

  1)创建一个集合sptSet(最短路径树集合),该集合跟踪最短路径树中包含的顶点,即,其与源点的最小距离已被计算并确定。最初,此集合为空。

  2)将距离值分配给输入图中的所有顶点。将所有距离值初始化为无穷大。将源顶点的距离值指定为0(dist[src] = 0),以便首先选择它。

  3)虽然当前的 sptSet (表示最短路径树)并不包含所有顶点:

  • 选择一个顶点 u,该顶点在 sptSet 中不存在,并且具有最小距离值。

  • 将u包含到 sptSet 中。

  • 更新u的所有相邻顶点的距离值。要更新距离值,要遍历所有相邻的顶点。对于每个相邻顶点 v,如果u(来自源点)的距离值和边缘u-v的权重之和小于v的距离值(dist[u] + graph[u][v] < dist[v]),则更新v的距离值。

  下面来看一个例子:

  集合 sptSet[] 最初为空,并且分配给每个顶点的距离为 dist[] = {0,INF,INF,INF,INF,INF,INF,INF},其中INF表示无穷大。 现在选择具有最小距离值的顶点。 选择顶点0,将其包含在 sptSet 中。 因此,sptSet 变为 {0}。 将 0 包含到 sptSet 之后,更新其相邻顶点的距离值。 0 的相邻顶点是 1 和 7。1 和 7 的距离值被更新为 4 和 8。下面的子图显示了顶点及其距离值,仅显示了具有有限距离值的顶点。 最短路径树中包含的顶点显示为绿色。

  选择具有最小距离值且尚未包含在最短路径树中的顶点(不在 sptSet 中)。 选择 顶点1 并将其添加到 sptSet。 因此,sptSet 现在变为 {0,1}。 更新相邻顶点的距离值1。顶点2 的距离值变为 12。

  选择具有最小距离值且尚未包含在最短路径树中的顶点(不在 sptSet 中)。 选择了顶点7。 因此,sptSet 现在变为 {0,1,7}。 更新相邻 顶点7 的距离值。顶点 6 和 8 的距离值变得有限(分别为 15 和 9)。

  选择具有最小距离值且尚未包含在最短路径树中的顶点(不在 sptSet 中)。选择了顶点6。因此,sptSet现在变为 {0,1,7,6}。更新相邻 顶点6 的距离值。更新顶点 5 和 8 的距离值。

  重复上述步骤,直到 sptSet 确实包含给定图的所有顶点。最后,我们得到以下最短路径树:

三、实现代码

  下面是使用了邻接矩阵的迪杰斯特拉算法实现。其算法的时间复杂度为 O(V2)。

 1     /**
2 * 为使用邻接矩阵表示的图实现Dijkstra的单源最短路径算法的函数
3 *
4 * @param graph 地图,给出的邻接矩阵
5 * @param src 源顶点
6 */
7 public void dijkstra(int[][] graph, int src) {
8 /* 输出数组,dist[i]将保存从src到i的最短距离 */
9 int[] dist = new int[V];
10
11 /* 如果顶点i包含在最短路径树中或从src到i的最短距离已确定,则sptSet[i]将为true */
12 Boolean[] sptSet = new Boolean[V];
13
14 /* 将所有距离初始化为无穷大并将stpSet[]初始化为false */
15 for (int i = 0; i < V; i++) {
16 dist[i] = Integer.MAX_VALUE;
17 sptSet[i] = false;
18 }
19
20 /* 源顶点与其自身的距离始终为0 */
21 dist[src] = 0;
22
23 /* 查找所有顶点的最短路径 */
24 for (int count = 0; count < V - 1; count++) {
25 int u = minDistance(dist, sptSet);
26
27 /* 将选取的顶点标记为已处理 */
28 sptSet[u] = true;
29
30 /* 更新选取的顶点的相邻顶点的dist值。*/
31 for (int v = 0; v < V; v++) {
32 /* 仅当不在sptSet中标记过且在u到v之间存在边且从src到通过u的v的路径的总权重小于dist[v]的当前值时,
33 才更新dist [v]。*/
34 if (!sptSet[v] && graph[u][v] != 0 && dist[u] != Integer.MAX_VALUE && dist[u] + graph[u][v] < dist[v]) {
35 dist[v] = dist[u] + graph[u][v];
36 }
37 }
38 }
39
40 /* 打印构造的最短距离数组 */
41 printSolution(dist);
42 }

  函数 minDistance(),从尚未包含在最短路径树中的一组顶点中查找具有最小距离值的顶点,就是算法从已知的最短路径树外选取距离远点比较近的顶点来进行边的扩展。此函数的时间复杂度为 O(V)。

 1     /**
2 * 从尚未包含在最短路径树中的一组顶点中查找具有最小距离值的顶点
3 *
4 * @param dist 存当前距离源点的最短路径
5 * @param sptSet 顶点是否存在于最短路树中
6 * @return
7 */
8 public int minDistance(int[] dist, Boolean[] sptSet) {
9 /* 初始化最小值 */
10 int min = Integer.MAX_VALUE;
11 int min_index = -1;
12
13 for (int v = 0; v < V; v++) {
14 if (!sptSet[v] && dist[v] <= min) {
15 min = dist[v];
16 min_index = v;
17 }
18 }
19
20 return min_index;
21 }

单源最短路径算法:迪杰斯特拉 (Dijkstra) 算法(一)的更多相关文章

  1. [C++]单源最短路径:迪杰斯特拉(Dijkstra)算法(贪心算法)

    1 Dijkstra算法 1.1 算法基本信息 解决问题/提出背景 单源最短路径(在带权有向图中,求从某顶点到其余各顶点的最短路径) 算法思想 贪心算法 按路径长度递增的次序,依次产生最短路径的算法 ...

  2. JS实现最短路径之迪杰斯特拉(Dijkstra)算法

    最短路径: 对于网图来说,最短路径是指两个顶点之间经过的边上权值和最少的路径,我们称第一个顶点是源点,最后一个顶点是终点 迪杰斯特拉 ( Dijkstra) 算法是并不是一下子就求出 了 Vo 到V8 ...

  3. 最短路径算法-迪杰斯特拉(Dijkstra)算法在c#中的实现和生产应用

    迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径. 它的主要特点是以起始点为中心向外层层扩展(广度优先遍历思想),直到扩展到终点为止 贪心算法(Greedy ...

  4. 迪杰斯特拉Dijkstra算法介绍

    迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径. 它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止. 基本思想 通过Dijk ...

  5. 最短路径-迪杰斯特拉(dijkstra)算法及优化详解

    简介: dijkstra算法解决图论中源点到任意一点的最短路径. 算法思想: 算法特点: dijkstra算法解决赋权有向图或者无向图的单源最短路径问题,算法最终得到一个最短路径树.该算法常用于路由算 ...

  6. 单源最短路径算法:迪杰斯特拉 (Dijkstra) 算法(二)

    一.基于邻接表的Dijkstra算法 如前一篇文章所述,在 Dijkstra 的算法中,维护了两组,一组包含已经包含在最短路径树中的顶点列表,另一组包含尚未包含的顶点.使用邻接表表示,可以使用 BFS ...

  7. 图的最短路径---迪杰斯特拉(Dijkstra)算法浅析

    什么是最短路径 在网图和非网图中,最短路径的含义是不一样的.对于非网图没有边上的权值,所谓的最短路径,其实就是指两顶点之间经过的边数最少的路径. 对于网图,最短路径就是指两顶点之间经过的边上权值之和最 ...

  8. 最短路径 - 迪杰斯特拉(Dijkstra)算法

    对于网图来说,最短路径,是指两顶点之间经过的边上权值之和最少的路径,并且我们称路径上的第一个顶点为源点,最后一个顶点为终点.最短路径的算法主要有迪杰斯特拉(Dijkstra)算法和弗洛伊德(Floyd ...

  9. C# 迪杰斯特拉(Dijkstra)算法

    Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止. 其基本思想是,设置顶点集合S并不断地作 ...

随机推荐

  1. Java优化if-else代码

    前言 开发系统一些状态,比如订单状态:数据库存储是数字或字母,但是需要显示中文或英文,一般用到if-else代码判断,但这种判断可读性比较差,也会影响后期维护,也比较容易出现bug.比如: 假设状态对 ...

  2. HDU1166敌兵布阵(线段树单点更新)

    线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点.       对于线段树中的每一个非叶子节点[a,b],它的左儿子表示的区间为[a,(a+b ...

  3. Docker安装flink及避坑指南

    Docker安装flink 导航 无处不在的大数据 安装flink 拉取flink镜像 编写docker-compose.yml 生成启动 查看安装效果 常见坑及解决方案 问题1 问题2 参考   本 ...

  4. 这个 MySQL bug 让我大开眼界

    这周收到一个 sentry 报警,如下 SQL 查询超时了. select * from order_info where uid = 5837661 order by id asc limit 1 ...

  5. spy++查找窗口句柄

    spy++可以用来查找桌面程序(c/s)的窗口句柄,实现自动化测试. def find_idxSubHandle(pHandle, winClass, index=0): ""&q ...

  6. SDA 课程

    课件总览 Slide1:Data Science & Digital Society Slide2:DEDA Digital Economy & Decision Analytics ...

  7. node ***.js或npm run scripts的脚本命令出现Cannot find module 'react-dev-utils/getPublicUrlOrPath'报错的解决办法

    出现类似Cannot find module 'react-dev-utils/getPublicUrlOrPath'一般是项目中没有下载报错中提到的模块(可以在项目中package.json文件de ...

  8. nodejs 安装 报错解决方案

    win10安装nodejs之后,查看版本号在终端输入node -v成功输出版本号,输入npm -v 之后报错...... 反复安装卸载之后,有点奔溃,最后的解决方案是:手动删除"C:\Use ...

  9. 使用ffmpeg进行视频图片提取

    环境:windows10-x64 ffmpeg的功能很强大,可以进行音频和视频的处理,这里记录下需要从视频文件提取图片的情况. ffmpeg官方地址:https://www.ffmpeg.org/使用 ...

  10. Java基础之(九):循环结构

    循环结构 前面我们已经聊过了if语句,接下来我们就聊聊跟选择语句一样常用的语句:循环语句. 同样的,所有的循环语句都可以写成for语句 while循环 while循环的格式: while(布尔表达式) ...