一、算法介绍

  迪杰斯特拉算法(英语: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反序列化漏洞Apache CommonsCollections分析

    Java反序列化漏洞Apache CommonsCollections分析 cc链,既为Commons-Collections利用链.此篇文章为cc链的第一条链CC1.而CC1目前用的比较多的有两条链 ...

  2. python工作中总结

    以下方法平时很少用,用其它解决方法,只是总结了一些其它同事的技巧 1   如何自动生成列表,加一个条件还能筛选 [x for x in range(10) if x>5 ] 来生一个字典试试 d ...

  3. 使用 elementUI 的表单进行查询,表单中只有一个文本框时,回车会自动触发表单的提交事件,导致页面的刷新。

    使用elementUI的el-form组件进行查询时,当输入框仅有一项时,回车自动提交表单,浏览器会刷新页面: 原因:由于当表单只有一个文本框时,按下回车将会触发表单的提交事件, 从而导致页面刷新. ...

  4. Ubuntu 引导修复

    Ubuntu 引导修复 前言 最近还在看 Docker 的教程,看到了"跨宿主机网络通信"的一节,于是想到去 Ubuntu 中 实践一番.结果发现 Ubuntu 进不去了.由于考虑 ...

  5. 机器学习——最优化问题:拉格朗日乘子法、KKT条件以及对偶问题

    1 前言 拉格朗日乘子法(Lagrange Multiplier)  和 KKT(Karush-Kuhn-Tucker)  条件是求解约束优化问题的重要方法,在有等式约束时使用拉格朗日乘子法,在有不等 ...

  6. css定位,class属性之间有空格与无空格的区别

    中间有空格的情况 是选择到.class1类下的.class2类子节点,即.class2类的节点要是.class1类子节点 <style> .class1 { color: black; } ...

  7. P5363-[SDOI2019]移动金币【阶梯博弈,dp,组合数学】

    正题 题目链接:https://www.luogu.com.cn/problem/P5363 题目大意 \(1\times n\)的网格上有\(m\)个硬币,两个人轮流向前移动一个硬币但是不能超过前一 ...

  8. 2017年第二届广东省强网杯线上赛WEB:Musee de X writeup(模板注入漏洞)

    目录 解题思路 总结 解题思路 拿到手上,有四个页面 首先按照题目要求执行,尝试注册一个名为admin的账户 这种情况,路径都给出来了,很可能就是目录遍历或者文件上传了 回到初始界面,点击链接here ...

  9. PyTorch固定参数

    In situation of finetuning, parameters in backbone network need to be frozen. To achieve this target ...

  10. virtualbox 桥接模式网络配置虚拟机之间通讯以及虚拟机联网

    一般来说桥接模式可以解决所有的网络问题 网卡选择 [root@HELLO network-scripts]# cat ifcfg-eth0 TYPE="Ethernet" PROX ...