① Dijkstra算法
Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。注意该算法要求图中不存在负权边。
设G=(V,E)是一个带权有向图,把图中顶点集合V分成两组,第一组为已求出最短路径的顶点集合(用S表示,初始时S中只有一个源点,以后每求得一条最短路径 , 就将加入到集合S中,直到全部顶点都加入到S中,算法就结束了),第二组为其余未确定最短路径的顶点集合(用U表示),按最短路径长度的递增次序依次把第二组的顶点加入S中。在加入的过程中,总保持从源点v到S中各顶点的最短路径长度不大于从源点v到U中任何顶点的最短路径长度含侍仿。此外,每个顶点对应一个距离,S中的顶点的距离就是从v到此顶点的最短路径长度,U中的顶点的距离,是从v到此顶点只包括S中的顶点为中间顶点的当前最短路径长度。
(1)初始时,S只包含起点D;U包含除D外的其他顶点,且U中顶点的距离为“起点D到该顶点的距离”(例如,U中顶点A的距离为[D,A]的长度,然后D和A不相邻,则谈枣A的距离为∞)
(2)从U中选出“距离最短的顶点K”,并将顶点K加入到S中;同时,从U中移除顶点K
(3)更新U中各个顶点到起点D的距离。之所以更新U中顶点的距离,是由于上一步谈纤中确定了K是求出最短路径的顶点,从而可以利用K来更新其他顶点到起点D的距离(例如,[D,A]的距离可能大于[D,K]+[K,A]的距离)
(4)重复步骤(2)和(3),直到遍历完所有顶点
https://blog.csdn.net/yalishadaa/article/details/55827681
② 最短路径算法(Dijkstra)
Dijkstra( 迪科斯特拉 )算法是用来解决核激唯单源最短路径的算法,要求路径权值非负数。该算法利用了深度优先搜索和贪心的算法。
下面是一个有权图,求从A到各个节点的最短路径。
第1步:从A点出发,判断每个点到A点的路径(如果该点不能直连A点则距离值为无穷大,如果该点能和A直连则是当前的权值),计算完之后把A点上色,结果如下图:
第2步:从除A点之外的点查找到距离A点最近的点C,从C点出发查找其邻近的节点(除去已上色的点),并重新计算C点的邻近点距离A点的值,如图中B点,若新值(C点到A点的值+C点到该点的路径)小于原值,则将值更新为5,同理更新D、E点。同时将C标铅陵记为已经处理过,如图所示涂色。
第3步:从上色的节点中查找距离A最近的B点,重复第3步操作。
第4步: 重复第3步,改培2步,直到所有的节点都上色。
最后就算出了从A点到所有点的最短距离。
leetcode 743题
③ 深入理解 Dijkstra 算法实现原理
(嗯,第一段是抄的,由于本人算法的基础比较薄弱,我会尽量用通俗易懂的高念语言来让大家理解本文)
参考博客: 数据结构--Dijkstra算法最清楚的讲解
大概就是这样一个有权图,液燃 Dijkstra 算法可以计算 任意节点 到 其他节点 的最短路径
2.执行上述 4、5两步骤,找出U集合中路径最短的节点D 加入S集合,并根据条件 if ( 'D 到 B,C,E 的距离' + 'AD 距离' < 'A 到 B,C,E 的距离' ) 来更新U集合
3.这时候 A->B, A->C 都为3,没关系戚埋困。其实这时候他俩都是最短距离,如果从算法逻辑来讲的话,会先取到B点。而这个时候 if 条件变成了 if ( 'B 到 C,E 的距离' + 'AB 距离' < 'A 到 C,E 的距离' ) , 如图所示这时候 A->B 距离 其实为 A->D->B
④ 简谈迪克斯特拉算法
一直想要学点简单的算法,叨叨了好久,开始吧【这篇文章的前言无非就是我想说点废话,大家可以选择性的过滤哈。】
迪杰斯特拉算法(Dijkstra)是由荷兰计算机科学家 狄克斯特拉 于1959 年提出的,因此又叫 狄克斯特拉算法 。是从一个顶点到其余各顶点的 最短路径 算法,解决的是有权图中最短路径问题。迪杰斯特拉算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。
敲黑板~进入正题
迪杰斯特拉算法是目前 OIER 们最爱用的最短路算法,下面讲一下这个算法的思路【图丑,请大家忍耐一下】:
第一步,我们先把a加入集合,数组变成(s = {a}, dis[] = {0, ∞,∞,∞,∞,∞,∞,∞})
第二步,找到和a最近的点,为b,把b加入集合,并确定他的最短路径【要注意箭头方向哈仿歼塌】,数组变成(s = {a, b}, dis[] ={0,2,∞,∞,∞,∞,∞,∞})
第三步,找到和b最近的点,为d,把d加入集合,并确定他的最短路径【要注意箭头方向】,数组变成(s = {a, b, d}, dis[] = {0,2,∞,3,∞,∞,∞,∞})
第四步,找到和d最近的点,为e,把e加入集合,并确定他的最短路径【要注意箭头方向】,数组变成(s = {a, b, d, e}, dis[] = {0,2,∞,3,5,∞,∞,∞改纤})
第五步,找到和e最近的点,为f,把f加入集合,并确定他的最短路径【要注意箭头方向】,数组变成(s = {a, b, d, e, f}, dis[] = {0,2,∞,3,5,9,∞,∞})
第六步,找到和f最近的点,为g,把g加入集合,并确定他的最短路径【要注意箭头方向】,数组变成(s = {a, b, d, e, f, g}, dis[] = {0,2,∞,3,5,9,12,∞})
第七步,目前只剩下c和h了,那么我们先要找到距离集合路径最短的c,把c加备圆入集合,并确定他的最短路径,数组变成(s = {a, b, c, d, e, f, g}, dis[]= {0,2,13,3,5,9,12,∞})
第八步,最后一步,我们找到距离集合路径最短的h,把h加入集合,并确定他的最短路径,数组变成(s = {a, b, c, d, e, f, g, h}, dis[] = {0,2,13,3,5,9,12,18})
得嘞,这个大致的思路是这样的,还有后续哟,欲知后事如何,请看下回讲解~
⑤ 最短路径 | 深入浅出Dijkstra算法(一)
上次我们介绍了神奇的只有 五行的 Floyd-Warshall 最短路算法 ,它可以方便的求得 任意两点的最短路径, 这称为 “多源最短路”。
这次来介绍 指定一个点(源点)到其余各个顶点的最短路径, 也叫做 “单源最短路径”。 例如求下图中的 1 号顶点到 2、3、4、5、6 号顶点的最短路径。
与 Floyd-Warshall 算法一样,这里仍然 使用二维数组 e 来存储顶点之间边的关系, 初始值如下。
我们还需要用 一个一维数组 dis 来存储 1 号顶点到其余各个顶点的初始路程, 我们可以称 dis 数组为 “距离表”, 如下。
我们将此时 dis 数组中的值称为 最短路的“估计值”。
既然是 求 1 号顶点到其余各个顶点的最短路程, 那就 先找一个离 1 号顶点最近的顶点。
通过数组 dis 可知当前离 1 号顶点最近是 2 号顶点。 当选择了 2 号顶点后,dis[2]的值就已经从“估计值”变为了“确定值”, 即 1 号顶点到 2 号顶点的最短路程就是当前 dis[2]值。
为什么呢?你想啊, 目前离 1 号顶点最近的是 2 号顶点,并且这个图所有的边都是正数,那么肯定不可能通过第三个顶点中转,使得 1 号顶点到 2 号顶点的路程进一步缩短了。 因此 1 号顶点到其它顶点的路程肯定没有 1 号到 2 号顶点短,对吧 O(∩_∩)O~
既然选了 2 号顶点,接下来再来看 2 号顶点 有哪些 出边 呢。有 2->3 和 2->4 这两条边。
先讨论 通过 2->3 这条边能否让 1 号顶点到 3 号顶点的路程变短。 也就是说现在来比较 dis[3] 和 dis[2]+e[2][3] 的大小。其中 dis[3]表示 1 号顶点到 3 号顶点的路程,dis[2]+e[2][3]中 dis[2]表示 1 号顶点到 2 号顶点的路程,e[2][3]表示 2->3 这条边。所以 dis[2]+e[2][3]就表示从 1 号顶点先到 2 号顶点,再通过 2->3 这条边,到达 3 号顶点的路程。
我们发现 dis[3]=12,dis[2]+e[2][3]=1+9=10,dis[3]>dis[2]+e[2][3],因此 dis[3]要更新为 10。这个过程有个专业术语叫做 “松弛” 。即 1 号顶点到 3 号顶点的路程即 dis[3],通过 2->3 这条边 松弛成功。 这便是 Dijkstra 算法的主要思想: 通过 “边” 来松弛 1 号顶点到其余各个顶点的路程。
同理通过 2->4(e[2][4]),可以将 dis[4]的值从 ∞ 松弛为 4(dis[4]初始为 ∞,dis[2]+e[2][4]=1+3=4,dis[4]>dis[2]+e[2][4],因此 dis[4]要更新为 4)。
刚才我们对 2 号顶点所有的出边进行了松弛。松弛完毕之后 dis 数组为:
接下来,继续在剩下的 3、4、5 和 6 号顶点中,选出离 1 号顶点最近的顶点。通过上面更新过 dis 数组,当前离 1 号顶点最近是 4 号顶点。此时,dis[4]的值已经从“估计值”变为了“确定值”。下面继续对 4 号顶点的所有出边(4->3,4->5 和 4->6)用刚才的方法进行松弛。松弛完毕之后 dis 数组为:
继续在剩下的 3、5 和 6 号顶点中,选出离 1 号顶点最近的顶点,这次选择 3 号顶点。此时,dis[3]的值已经从“估计值”变为了“确定值”。对 3 号顶点的所有出边(3->5)进行松弛。松弛完毕之后 dis 数组为:
继续在剩下的 5 和 6 号顶点中,选出离 1 号顶点最近的顶点,这次选择 5 号顶点。此时,dis[5]的值已经从“估计值”变为了“确定值”。对5号顶点的所有出边(5->4)进行松弛。松弛完毕之后 dis 数组为:
最后对 6 号顶点的所有出边进行松弛。因为这个例子中 6 号顶点没有出边,因此不用处理。 到此,dis 数组中所有的值都已经从“估计值”变为了“确定值”。
最终 dis 数组如下,这便是 1 号顶点到其余各个顶点的最短路径。
OK,现在来总结一下刚才的算法。 Dijkstra算法的基本思想是:每次找到离源点(上面例子的源点就是 1 号顶点)最近的一个顶点,然后以该顶点为中心进行扩展,最终得到源点到其余所有点的最短路径。
基本步骤如下:
在 博客 中看到两个比较有趣的问题,也是在学习Dijkstra时,可能会有疑问的问题。
当我们看到上面这个图的时候,凭借多年对平面几何的学习,会发现在“三角形ABC”中,满足不了 构成三角形的条件(任意两边之和大于第三边)。 纳尼,那为什么图中能那样子画?
还是“三角形ABC”,以A为起点,B为终点,如果按照平面几何的知识, “两点之间线段最短”, 那么,A到B的最短距离就应该是6(线段AB),但是,实际上A到B的最短距离却是3+2=5。这又怎么解释?
其实,之所以会有上面的疑问,是因为 对边的权值和边的长度这两个概念的混淆, 。之所以这样画,也只是为了方便理解(每个人写草稿的方式不同,你完全可以用别的方式表示,只要便于你理解即可)。
PS:数组实现邻接表可能较难理解,可以看一下 这里
参考资料:
Dijkstra算法是一种基于贪心策略的算法。每次新扩展一个路程最短的点,更新与其相邻的点的路程。当所有边权都为正时,由于不会存在一个路程更短的没扩展过的点,所以这个点的路程永远不会再被改变,因而保证了算法的正确性。
根据这个原理, 用Dijkstra算法求最短路径的图不能有负权边, 因为扩展到负权边的时候会产生更短的路径,有可能破坏了已经更新的点路径不会发生改变的性质。
那么,有没有可以求带负权边的指定顶点到其余各个顶点的最短路径算法(即“单源最短路径”问题)呢?答案是有的, Bellman-Ford算法 就是一种。(我们已经知道了 Floyd-Warshall 可以解决“多源最短路”问题,也要求图的边权均为正)
通过 邻接矩阵 的Dijkstra时间复杂度是 。其中每次找到离 1 号顶点最近的顶点的时间复杂度是 O(N),这里我们可以用 优先队列(堆) 来优化,使得这一部分的时间复杂度降低到 。这个我们将在后面讨论。
⑥ 迪克斯特拉算法结果怎么看解释一下
这个算法最后的结果就是一旁信个点到图中每一个点的最短距离。比如一个图中有A,B,C,D,E,F,G七个点,你要求A到轿祥其他每一个点的最短距离,那么最后的结果应该是类似A到B最短距离XXX,A到C最短距离XXX,A到D最短距离XXX,闭启搏……
应该是很简单的。
题主你为什么看不懂?
⑦ 【数据结构】最短路径之迪杰斯特拉(Dijkstra)算法与弗洛伊德(Floyd)算法
迪杰斯特拉(Dijkstra)算法核心: 按照路径长度递增的次序产生最短路径。
迪杰斯特拉(Dijkstra)算法步骤:(求图中v0到v8的最短路径)并非一下子求出v0到v8的最短路径,而是 一步一步求出它们之间顶点的最短路径 ,过过程中都是 基于已经求出的最短路径的基础上,求得更远顶点的最短路径,最终得出源点与终点的最短路径 。
弗洛伊德(Floyd)算法是一个经典的 动态规划算法 。
⑧ dijkstra算法是什么
迪杰斯特拉算法用来解决从顶点v0出发到其余顶点的最短路径,该算法按照最短路径长度递增的顺序产生所以最短路径。
对于图G=(V,E),将图中的顶点分成两组:第一组S:已求出的最短路径的终点集合(开始为{v0})。第二组V-S:尚未求出最短路径的终点集合(开始为V-{v0}的全部结点)。
堆优化
思考
该算法复杂度为n^2,我们可以发现,如果边数远小于n^2,对此可以考虑用堆这种数据结构进行优化,取出最短路径的复杂度降为O(1);每次调整的复杂度降为O(elogn);e为该点的边数,所以复杂度降为O((m+n)logn)。
实现
1、将源点加入堆,并调整堆。
2、选出堆顶元素u(即代价最小的元素),从堆中删除,并对堆进行调整。
3、处理与u相邻的,未被访问过的,满足三角不等式的顶点
1):若该点在堆里,更新距离,并调整该元素在堆中的位置。
2):若该点不在堆里,加入堆,更新堆。
4、若取到的u为终点,结束算法;否则重复步骤2、3。
⑨ 迪杰斯特拉算法的本质是贪心还是动态规划
我认为 Dijkstra算法 的本质是 广度优先搜索,
而此处的广度是定义在路程的cost之上的。
(就好比从圆心处向外扩散一个圆环,首次碰到的就是最近)
动态规划泛指,重叠子问题与原问题的推算关系(学名:动态转移方程),
贪心是极端情况的斗升芦动态规划,子问题独一选择性。
Dijkstra算法的分解思路是
到达某节点的cost最小路径 --(从这里面选)--> { 到达其相邻节点的cost最小路径 }
独一选择性:
只挑选空带: Min {到达其相邻节点笑并的最短路径}
结论:的确是贪心策略
请采纳。
⑩ dijkstra算法是什么
Dijkstra算法是由荷兰计算机科学家狄克斯特拉(Dijkstra)于1959年提出的,因此又叫狄克斯特拉算法。是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题。
其基本原理是:每次新扩展一个距离最短的点,更新与其相邻的点的距离。当所有边权都为正时,由于不会存在一个距离更短的没扩展过的点,所以这个点的距离永远不会再被改变,因而保证了算法的正确性。
不过根据这个原理,用Dijkstra求最短路的图不能有负权边,因为扩展到负权边的时候会产生更短的距离,有可能就破坏了已经更新的点距离不会改变的性质。
举例来说,如果图中的顶点表示城市,而边上的权重表示着城市间开车行经的距离。Dijkstra算法可以用来找到两个城市之间的最短路径。
Dijkstra算法的输入包含了一个有权重的有向图G,以及G中的一个来源顶点S。我们以V表示G中所有顶点的集合。每一个图中的边,都是两个顶点所形成的有序元素对。(u,v)表示从顶点u到v有路径相连。我们以E所有边的集合,而边的权重则由权重函数w: E→[0,∞]定义。
因此,w(u,v)就是从顶点u到顶点v的非负花费值(cost)。边的花费可以想象成两个顶点之间的距离。任两点间路径的花费值,就是该路径上所有边的花费值总和。
已知有V中有顶点s及t,Dijkstra算法可以找到s到t的最低花费路径(i.e.最短路径)。这个算法也可以在一个图中,找到从一个顶点s到任何其他顶点的最短路径。