图最短路径之Dijkstra
Dijkstra’s shortest path algorithm
算法参考地址:Dijsktra's algorithm (geeksforgeeks.org)
算法的简介:
1)该算法用来计算最短距离,但不计算路径信息。我们可以创建一个父数组,在距离更新时更新父数组如[prim的实现,并使用它来显示从源到不同顶点的最短路径。 2)代码用于无向图,相同的Dijkstra函数也可以用于有向图。 3) 代码查找从源到所有顶点的最短距离。如果我们只对从源到单个目标的最短距离感兴趣,我们可以在选取的最小距离顶点等于目标时中断for循环(算法的步骤3.a)。 4) 实现的时间复杂度为 O(V^2)。如果输入,则可以借助二进制堆将其简化为 O(E log V)。 5)Dijkstra的算法不适用于具有负权重周期的图形。对于具有负边的图形,可以使用Floyd或者Bellman-Ford算法。
算法的过程
给定图形和图形中的源顶点,查找从源到给定图形中所有顶点的最短路径。 Dijkstra的算法与[Prim的最小生成树算法]非常相似。与Prim的MST一样,我们生成一个SPT(最短路径树),以给定的源作为根。我们维护两个集合,一个集合包含最短路径树中包含的顶点,另一个集合包含尚未包含在最短路径树中的顶点。在算法的每一步中,我们都会找到一个位于另一个集合(尚未包含的集合)中的顶点,并且与源的距离最小。 以下是Dijkstra算法中使用的详细步骤,用于查找从单个源顶点到给定图中所有其他顶点的最短路径。
算法 1) 创建一个集合 sptSet(最短路径树集),用于跟踪最短路径树中包含的顶点,即计算并最终确定其与源的最小距离。最初,此集为空。 2) 为输入图中的所有顶点分配距离值。将所有距离值初始化为 INFINITE。为源顶点指定距离值为 0,以便首先选取它。 3) 虽然 sptSet 不包括所有顶点 ....a) 选择一个在 sptSet 中不存在且具有最小距离值的顶点 u。 ....b) 将您包括在 sptSet 中。 ....c) 更新您所有相邻顶点的距离值。要更新距离值,请循环访问所有相邻顶点。对于每个相邻顶点 v,如果 u 的距离值(来自源)和边 u-v 的权重之和小于 v 的距离值,则更新 v 的距离值。
让我们通过以下示例来理解:
设置的 sptSet 最初是空的,分配给顶点的距离是 {0, INF, INF, INF, INF, INF, INF} ,其中 INF 表示无限。现在选取具有最小距离值的顶点。选取顶点 0,将其包含在 sptSet 中。所以sptSet变得{0}。在 sptSet 中包含 0 后,更新其相邻顶点的距离值。相邻顶点 0 为 1 和 7。距离值 1 和 7 将更新为 4 和 8。以下子图显示顶点及其距离值,仅显示具有有限距离值的顶点。SPT 中包含的顶点以绿色显示。
选取具有最小距离值且尚未包含在 SPT(不在 sptSET 中)的顶点。选取顶点 1 并将其添加到 sptSet 中。所以 sptSet 现在变成 {0, 1}。更新相邻顶点 1 的距离值。顶点 2 的距离值变为 12。
选取具有最小距离值且尚未包含在 SPT(不在 sptSET 中)的顶点。选取顶点 7。所以 sptSet 现在变成 {0, 1, 7}。更新相邻顶点的距离值 7。顶点 6 和 8 的距离值变为有限(分别为 15 和 9)。
选取具有最小距离值且尚未包含在 SPT(不在 sptSET 中)的顶点。选取顶点 6。所以 sptSet 现在变成 {0, 1, 7, 6}。更新相邻顶点 6 的距离值。将更新顶点 5 和 8 的距离值。
我们重复上述步骤,直到 sptSet 包含给定图形的所有顶点。最后,我们得到以下最短路径树(SPT)。
我们使用布尔数组 sptSet[] 来表示 SPT 中包含的顶点集。如果值 sptSet[v] 为真,则顶点 v 包含在 SPT 中,否则不包含。数组 dist[] 用于存储所有顶点的最短距离值。
算法的实现
golang
// F 代表两点之间不可达
const F = 10000
func dijkstra(graph [][]int, source int) []int {
n := len(graph)
if source >= n {
return []int{}
}
dist := make([]int, n)
visited := make([]bool, n)
for i := 0; i < n; i++ {
dist[i] = graph[source][i]
visited[i] = false
}
dist[source] = 0
visited[source] = true
for i := 1; i < n; i++ {
temMinDis := F
curIdx := -1
for j := 0; j < n; j++ {
if !visited[j] && dist[j] < temMinDis {
temMinDis = dist[j]
curIdx = j
}
}
visited[curIdx] = true
dist[curIdx] = temMinDis
for k := 0; k < n; k++ {
if !visited[k] && dist[curIdx]+graph[curIdx][k] < dist[k] {
dist[k] = dist[curIdx] + graph[curIdx][k]
}
}
}
return dist
}
Java
package graph.dijkstra;
import java.util.Arrays;
public class ShortestPathOfDijkstra {
private static final int MAX = 10000;
/**
* 接受一个有向图的权重矩阵,和一个起点编号start(从0编号,顶点存在数组中)
*
* @param graph graph
* @param startPointIndex startPointIndex
* @return 返回一个int[] 数组,表示从start到它的最短路径长度
*/
public static int[] dijsktra(int[][] graph, int startPointIndex) {
int length = graph.length;
//标记当前该顶点的最短路径是否已经求出,true表示已经求出
boolean[] visited = new boolean[length];
//start点的最短距离已经求出
for (int i = 0; i < graph.length; i++) {//初始化s集合,只有起始点
if (i == startPointIndex) {
visited[i] = true;
} else {
visited[i] = false;
}
}
//存放从start到各个点的最短距离
int[] shortDistance = new int[length];
for (int i = 0; i < graph.length; i++) {//初始化,起始点到其他点的距离。
shortDistance[i] = graph[startPointIndex][i];
}
//start到他本身的距离最短为0
shortDistance[startPointIndex] = 0;
//存放从start点到各点的最短路径的字符串表示
String[] path = new String[length];
for (int i = 0; i < length; i++) {
path[i] = startPointIndex + "->" + i;
}
for (int count = 1; count < length; count++) {
int k = -1;
int dmin = MAX;
for (int i = 0; i < length; i++) {
if (!visited[i] && shortDistance[i] < dmin) {
dmin = shortDistance[i];
k = i;
}
}
//选出一个距离start最近的未标记的顶点 将新选出的顶点标记为以求出最短路径,且到start的最短路径为dmin。
shortDistance[k] = dmin;
visited[k] = true;
//以k为中间点,修正从start到未访问各点的距离
for (int i = 0; i < length; i++) {
if (!visited[i] && shortDistance[k] + graph[k][i] < shortDistance[i]) {
shortDistance[i] = shortDistance[k] + graph[k][i];
path[i] = path[k] + "->" + i;
}
}
}
for (int i = 0; i < length; i++) {
System.out.println("从" + startPointIndex + "出发到" + i + "的最短路径为:" + path[i] + "=" + shortDistance[i]);
}
return shortDistance;
}
public static void main(String[] args) {
int[][] graph = {
{0, 4, 6, 6, MAX, MAX, MAX},
{MAX, 0, 1, MAX, 7, MAX, MAX},
{MAX, MAX, 0, MAX, 6, 4, MAX},
{MAX, MAX, 2, 0, MAX, 5, MAX},
{MAX, MAX, MAX, MAX, 0, MAX, 6},
{MAX, MAX, MAX, MAX, 1, 0, 8},
{MAX, MAX, MAX, MAX, MAX, MAX, MAX}};
int start = 0;
int[] dijsktra = dijsktra(graph, start);
System.out.println(Arrays.toString(dijsktra));
}
}
图最短路径之Dijkstra的更多相关文章
- 算法学习记录-图——最短路径之Dijkstra算法
在网图中,最短路径的概论: 两顶点之间经过的边上权值之和最少的路径,并且我们称路径上的第一个顶点是源点,最后一个顶点是终点. 维基百科上面的解释: 这个算法是通过为每个顶点 v 保留目前为止所找到的从 ...
- 有向有权图的最短路径算法--Dijkstra算法
Dijkstra算法 1.定义概览 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.Di ...
- Dijkstra含权图最短路径;审判,不要错过枚举退款保证不会重复;国际象棋八皇后问题
求两节点的最短通路.对于无权图,能够通过图的广度优先遍历求解.含权图一般通过Dijkstra算法求解. import java.util.ArrayList; import java.util.Has ...
- 最短路径算法Dijkstra和A*
在设计基于地图的游戏,特别是isometric斜45度视角游戏时,几乎必须要用到最短路径算法.Dijkstra算法是寻找当前最优路径(距离原点最近),如果遇到更短的路径,则修改路径(边松弛). Ast ...
- 最短路径算法——Dijkstra,Bellman-Ford,Floyd-Warshall,Johnson
根据DSqiu的blog整理出来 :http://dsqiu.iteye.com/blog/1689163 PS:模板是自己写的,如有错误欢迎指出~ 本文内容框架: §1 Dijkstra算法 §2 ...
- 单源最短路径(dijkstra算法)php实现
做一个医学项目,当中在病例评分时会用到单源最短路径的算法.单源最短路径的dijkstra算法的思路例如以下: 如果存在一条从i到j的最短路径(Vi.....Vk,Vj),Vk是Vj前面的一顶点.那么( ...
- 最短路径算法-Dijkstra算法的应用之单词转换(词梯问题)(转)
一,问题描述 在英文单词表中,有一些单词非常相似,它们可以通过只变换一个字符而得到另一个单词.比如:hive-->five:wine-->line:line-->nine:nine- ...
- 最短路径算法——Dijkstra算法
在路由选择算法中都要用到求最短路径算法.最出名的求最短路径算法有两个,即Bellman-Ford算法和Dijkstra算法.这两种算法的思路不同,但得出的结果是相同的. 下面只介绍Dijkstra算法 ...
- 最短路径之Dijkstra算法和Floyd-Warshall算法
最短路径算法 最短路径算法通常用在寻找图中任意两个结点之间的最短路径或者是求全局最短路径,像是包括Dijkstra.A*.Bellman-Ford.SPFA(Bellman-Ford的改进版本).Fl ...
- 【算法设计与分析基础】25、单起点最短路径的dijkstra算法
首先看看这换个数据图 邻接矩阵 dijkstra算法的寻找最短路径的核心就是对于这个节点的数据结构的设计 1.节点中保存有已经加入最短路径的集合中到当前节点的最短路径的节点 2.从起点经过或者不经过 ...
随机推荐
- Selenium使用总结:加载Flash、禁用JS、滚动页面至元素、缩放页面
前言 前几周做了个使用Selenium的项目,踩了好多好多好多的Selenium的坑,越来越感觉他作为一个第三方库,对于Chrome的操作实在是有局限.另外,推荐大家一个Selenium之外的操作浏览 ...
- SpringBoot-mybatis-plus 分页
前言: 想必数据分页对于每一个程序员并不陌生,针对分页查询功能代码实现上:肯定是代码简洁明了且能达到分页的效果会更好! 现在我将基于SpringBoot - mybatisPlus分页查询的方法总结如 ...
- UE4 InstancedStaticMesh使用
在绘制大批量近似模型时,Unity有GPU Instancing(https://www.cnblogs.com/hont/p/7143626.html),而UE中有 HISM和ISM(Instanc ...
- The attempt was made from the following location: com.ruoyi.framework.config.ResourcesConfig.corsFilter(ResourcesConfig.java:57)
报错信息: 8:42:12.529 [restartedMain] ERROR o.s.b.w.e.t.TomcatStarter - [onStartup,61] - Error starting ...
- C 语言编程 — 输入/输出与文件操作
目录 文章目录 目录 前文列表 输入/输出 scanf() 和 printf() getchar() 和 putchar() 文件操作 打开文件 关闭文件 写入文件 读取文件 二进制 I/O 函数 前 ...
- PageOffice 6 版本最简单的打开保存文件
在OA办公.文档流转等各个Web系统中,实现最简单的打开编辑保存文件功能,调用PageOffice只需要几行代码就可以完成. 后端代码 在后端编写代码调用webOpen方法打开文件之前给SaveFil ...
- 降本提效 | AIRIOT设备运维管理解决方案
传统运维多是使用在本地化系统,以人工运维和独立系统执行运维工作,重点关注的是设施运行,存在以下几个问题: 1.信息孤岛:本地化系统的接口不同,功能单一独立,各个系统之间的数据无法对接.交互,形 ...
- 工业福利!用.NET快速开发物联网扫码器设备的通用扫码功能
不管你是用.net framework还是用.net core或者更高版本.net环境,这篇文章也许都能帮到你!因为接下来我会提供一个简单粗暴的方式,来快速实现多款扫码器的通用扫码功能.目前本地测试过 ...
- # [NOIP2011 提高组] 铺地毯
传送锚点:https://www.luogu.com.cn/problem/P1003 题目描述 为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形 ...
- ubuntu docker 解决sudo权限问题
#如果还没有 docker group 就添加一个:$sudo groupadd docker#将用户加入该 group 内.然后退出并重新登录就生效啦.$sudo gpasswd -a ${USER ...