当前位置:首页 » 操作系统 » a最短路径算法

a最短路径算法

发布时间: 2023-07-17 03:20:36

1. 最短路径算法(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题

2. 图遍历算法之最短路径Dijkstra算法

最短路径问题是图论研究中一个经典算法问题,旨在寻找图中两节点或单个节点到其他节点之间的最短路径。根据问题的不同,算法的具体形式包括:

常用的最短路径算法包括:Dijkstra算法,A 算法,Bellman-Ford算法,SPFA算法(Bellman-Ford算法的改进版本),Floyd-Warshall算法,Johnson算法以及Bi-direction BFS算法。本文将重点介绍Dijkstra算法的原理以及实现。

Dijkstra算法,翻译作戴克斯特拉算法或迪杰斯特拉算法,于1956年由荷兰计算机科学家艾兹赫尔.戴克斯特拉提出,用于解决赋权有向图的 单源最短路径问题 。所谓单源最短路径问题是指确定起点,寻找该节点到图中任意节点的最短路径,算法可用于寻找两个城市中的最短路径或是解决着名的旅行商问题。

问题描述 :在无向图 中, 为图节点的集合, 为节点之间连线边的集合。假设每条边 的权重为 ,找到由顶点 到其余各个节点的最短路径(单源最短路径)。

为带权无向图,图中顶点 分为两组,第一组为已求出最短路径的顶点集合(用 表示)。初始时 只有源点,当求得一条最短路径时,便将新增顶点添加进 ,直到所有顶点加入 中,算法结束。第二组为未确定最短路径顶点集合(用 表示),随着 中顶点增加, 中顶点逐渐减少。

以下图为例,对Dijkstra算法的工作流程进行演示(以顶点 为起点):

注:
01) 是已计算出最短路径的顶点集合;
02) 是未计算出最短路径的顶点集合;
03) 表示顶点 到顶点 的最短距离为3
第1步 :选取顶点 添加进


第2步 :选取顶点 添加进 ,更新 中顶点最短距离




第3步 :选取顶点 添加进 ,更新 中顶点最短距离




第4步 :选取顶点 添加进 ,更新 中顶点最短距离





第5步 :选取顶点 添加进 ,更新 中顶点最短距离



第6步 :选取顶点 添加进 ,更新 中顶点最短距离



第7步 :选取顶点 添加进 ,更新 中顶点最短距离

示例:node编号1-7分别代表A,B,C,D,E,F,G

(s.paths <- shortest.paths(g, algorithm = "dijkstra"))输出结果:

(s.paths <- shortest.paths(g,4, algorithm = "dijkstra"))输出结果:

示例:

找到D(4)到G(7)的最短路径:

[1] 维基网络,最短路径问题: https://zh.wikipedia.org/wiki/%E6%9C%80%E7%9F%AD%E8%B7%AF%E9%97%AE%E9%A2%98 ;
[2]CSDN,Dijkstra算法原理: https://blog.csdn.net/yalishadaa/article/details/55827681 ;
[3]RDocumentation: https://www.rdocumentation.org/packages/RNeo4j/versions/1.6.4/topics/dijkstra ;
[4]RDocumentation: https://www.rdocumentation.org/packages/igraph/versions/0.1.1/topics/shortest.paths ;
[5]Pypi: https://pypi.org/project/Dijkstar/

3. 最短路径问题5种类型

最短路径问题5种类型有Dijkstra算法、A*算法、SPFA算法、Bellman-Ford算法和Floyd-Warshall算法,

扩展知识:

用于解决最短路径问题的算法被称做“最短路径算法”,有时被简称作“路径算法”。最常用的路径算法有:
Dijkstra算法、A*算法、SPFA算法、Bellman-Ford算法和Floyd-Warshall算法,本文主要介绍其中的三种。
最短路径问题是图论研究中的一个经典算法问题,旨在寻找图(由结点和路径组成的)中两结点之间的最短路径。
算法具体的形式包括:确定起点的最短路径问题:即已知起始结点,求最短路径的问题。
确定终点的最短路径问题:与确定起点的问题相反,该问题是已知终结结点,求最短路径的问题。在无向图中该问题与确定起点的问题完全等同,在有向图中该问题等同于把所有路径方向反转的确定起点的问题。
确定起点终点的最短路径问题:即已知起点和终点,求两结点之间的最短路径。

4. A*算法优化

A算法是游戏中路径搜索的常见算法。Dijkstra是最短路径的经典算法,A算法的思路基本上和Dijkstra算法一致,在Dijkstra算法的基础上增加了启发函数,也就是:

f(n) = g(n) + h(n)

其中,n是路径上某一点,g(n)是从出发点到该点的cost,h(n)是关于该点的启发函数,通常是对从该点到目标花费的一个估计,例如到目标的直线距离或者曼哈顿距离。 A算法每次选择f(n)最小的点,然后更新所有g(n)。
如果你明白Dijkstra算法,那么在这里h(n) = 0 的话,A算法就和Dijkstra算法一样了。
本文不详细讲解A算法,需要详细了解A算法的具体过程的,参见以下两篇文章:

理解A*算法的具体过程
A*算法详解

A*算法优化的关键在于h(n)的选择。 一个启发函数h(n)被称为admissible的,是指h(n)的估计,不会超过节点N到目标的实际花费。
如果h(x)满足以下条件,h(x)被称为单调的(monotone, or consistent)。 对于任意一条边(x,y),
h(x) <= d(x,y) + h(y)
其中d(x,y)是(x,y)的长度

如果满足这个条件,就意味着没有任何节点需要被处理多次,也就是说,在Dijkstra算法中,新加入一个节点会导致已添加节点中cost降低的情况不会存在,也就不需要去更新已添加节点(称为close set)。

如果一个启发函数是单调的,那么该启发函数一定是admissible的。如果该启发函数是admissible的,那么可以证明A*在同类算法中搜寻到最短的路径。

问题出在这里:如果我们更在意的是搜索的时间空间花费,而不是最优结果,那么A*算法就有优化空间。所以我们放松要求,修改我们的启发函数,使得我们搜寻到的路径不会比最佳路径差太多,就是优化算法,称为ε-admissible算法。

有多种ε-admissible算法,在此只举例最简单直接的一种: 加权A*(静态加权)算法。

假如ha(n)是一个admissible的启发函数,我们选取新的启发函数hw(n) = ε ha(n),其中ε>1 作为启发函数。就可以在某种程度上进行优化。 下图1是使用ha(n)作为启发式算法,下图2是使用hw(n)作为启发式算法,其中ε取5.

图1:ha(x)作为启发算法

图2:hn(x)作为启发算法

可以看出,ha(n)可以找到最小路径,但是多了许多无用的搜索;而hw(n)找到的不是最优路径,但是减少了大量无用搜索。
其他的优化算法思路类似都是在于启发函数的选择。详见参考文献。

参考文献:
https://en.wikipedia.org/wiki/A*_search_algorithm#Admissibility_and_optimality https://en.wikipedia.org/wiki/Consistent_heuristic

5. 最短路径算法

Dijkstra算法,A*算法和D*算法

Dijkstra算法是典型最短路算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法能得出最短路径的最优解,但由于它遍历计算的节点很多,所以效率低。

Dijkstra算法是很有代表性的最短路算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等。

Dijkstra一般的表述通常有两种方式,一种用永久和临时标号方式,一种是用OPEN, CLOSE表方式,Drew为了和下面要介绍的 A* 算法和 D* 算法表述一致,这里均采用OPEN,CLOSE表的方式。

大概过程:
创建两个表,OPEN, CLOSE。
OPEN表保存所有已生成而未考察的节点,CLOSED表中记录已访问过的节点。
1. 访问路网中里起始点最近且没有被检查过的点,把这个点放入OPEN组中等待检查。
2. 从OPEN表中找出距起始点最近的点,找出这个点的所有子节点,把这个点放到CLOSE表中。
3. 遍历考察这个点的子节点。求出这些子节点距起始点的距离值,放子节点到OPEN表中。
4. 重复2,3,步。直到OPEN表为空,或找到目标点。

提高Dijkstra搜索速度的方法很多,常用的有数据结构采用Binary heap的方法,和用Dijkstra从起始点和终点同时搜索的方法。

A*(A-Star)算法是一种启发式算法,是静态路网中求解最短路最有效的方法。

公式表示为: f(n)=g(n)+h(n),
其中f(n) 是节点n从初始点到目标点的估价函数,
g(n) 是在状态空间中从初始节点到n节点的实际代价,
h(n)是从n到目标节点最佳路径的估计代价。

保证找到最短路径(最优解的)条件,关键在于估价函数h(n)的选取:
估价值h(n)<= n到目标节点的距离实际值,这种情况下,搜索的点数多,搜索范围大,效率低。但能得到最优解。
如果 估价值>实际值, 搜索的点数少,搜索范围小,效率高,但不能保证得到最优解。
估价值与实际值越接近,估价函数取得就越好。
例如对于几何路网来说,可以取两节点间欧几理德距离(直线距离)做为估价值,即f=g(n)+sqrt((dx-nx)*(dx-nx)+(dy-ny)*(dy-ny));这样估价函数f在g值一定的情况下,会或多或少的受估价值h的制约,节点距目标点近,h值小,f值相对就小,能保证最短路的搜索向终点的方向进行。明显优于Dijstra算法的毫无无方向的向四周搜索。
conditions of heuristic
Optimistic (must be less than or equal to the real cost)
As close to the real cost as possible
主要搜索过程:
创建两个表,OPEN表保存所有已生成而未考察的节点,CLOSED表中记录已访问过的节点。
遍历当前节点的各个节点,将n节点放入CLOSE中,取n节点的子节点X,->算X的估价值->
While(OPEN!=NULL)
{
从OPEN表中取估价值f最小的节点n;
if(n节点==目标节点) break;
else
{
if(X in OPEN) 比较两个X的估价值f //注意是同一个节点的两个不同路径的估价值
if( X的估价值小于OPEN表的估价值 )
更新OPEN表中的估价值; //取最小路径的估价值
if(X in CLOSE) 比较两个X的估价值 //注意是同一个节点的两个不同路径的估价值
if( X的估价值小于CLOSE表的估价值 )
更新CLOSE表中的估价值; 把X节点放入OPEN //取最小路径的估价值
if(X not in both)
求X的估价值;
并将X插入OPEN表中; //还没有排序
}
将n节点插入CLOSE表中;
按照估价值将OPEN表中的节点排序; //实际上是比较OPEN表内节点f的大小,从最小路径的节点向下进行。
}

A*算法和Dijistra算法的区别在于有无估价值,Dijistra算法相当于A*算法中估价值为0的情况。

动态路网,最短路算法 D*A* 在静态路网中非常有效(very efficient for static worlds),但不适于在动态路网,环境如权重等不断变化的动态环境下。

D*是动态A*(D-Star,Dynamic A*) 卡内及梅隆机器人中心的Stentz在1994和1995年两篇文章提出,主要用于机器人探路。是火星探测器采用的寻路算法。

主要方法:
1.先用Dijstra算法从目标节点G向起始节点搜索。储存路网中目标点到各个节点的最短路和该位置到目标点的实际值h,k(k为所有变化h之中最小的值,当前为k=h。每个节点包含上一节点到目标点的最短路信息1(2),2(5),5(4),4(7)。则1到4的最短路为1-2-5-4。
原OPEN和CLOSE中节点信息保存。
2.机器人沿最短路开始移动,在移动的下一节点没有变化时,无需计算,利用上一步Dijstra计算出的最短路信息从出发点向后追述即可,当在Y点探测到下一节点X状态发生改变,如堵塞。机器人首先调整自己在当前位置Y到目标点G的实际值h(Y),h(Y)=X到Y的新权值c(X,Y)+X的原实际值h(X).X为下一节点(到目标点方向Y->X->G),Y是当前点。k值取h值变化前后的最小。
3.用A*或其它算法计算,这里假设用A*算法,遍历Y的子节点,点放入CLOSE,调整Y的子节点a的h值,h(a)=h(Y)+Y到子节点a的权重C(Y,a),比较a点是否存在于OPEN和CLOSE中,方法如下:
while()
{
从OPEN表中取k值最小的节点Y;
遍历Y的子节点a,计算a的h值 h(a)=h(Y)+Y到子节点a的权重C(Y,a)
{
if(a in OPEN) 比较两个a的h值
if( a的h值小于OPEN表a的h值 )
{ 更新OPEN表中a的h值;k值取最小的h值
有未受影响的最短路经存在
break;
}
if(a in CLOSE) 比较两个a的h值 //注意是同一个节点的两个不同路径的估价值
if( a的h值小于CLOSE表的h值 )
{
更新CLOSE表中a的h值; k值取最小的h值;将a节点放入OPEN表
有未受影响的最短路经存在
break;
}
if(a not in both)
将a插入OPEN表中; //还没有排序
}
放Y到CLOSE表;
OPEN表比较k值大小进行排序;
}
机器人利用第一步Dijstra计算出的最短路信息从a点到目标点的最短路经进行。

D*算法在动态环境中寻路非常有效,向目标点移动中,只检查最短路径上下一节点或临近节点的变化情况,如机器人寻路等情况。对于距离远的最短路径上发生的变化,则感觉不太适用。

6. 什么是 a算法a* 算法有什么特点

A*算法:A*(A-Star)算法是一种静态路网中求解最短路径最有效的直接搜索方法。估价值与实际值越接近,估价函数取得就越好
A* (A-Star)算法是一种静态路网中求解最短路最有效的直接搜索方法。
注意是最有效的直接搜索算法。之后涌现了很多预处理算法(ALT,CH,HL等等),在线查询效率是A*算法的数千甚至上万倍。
公式表示为: f(n)=g(n)+h(n),
其中 f(n) 是从初始点经由节点n到目标点的估价函数,
g(n) 是在状态空间中从初始节点到n节点的实际代价,
h(n) 是从n到目标节点最佳路径的估计代价。
保证找到最短路径(最优解的)条件,关键在于估价函数f(n)的选取:
估价值h(n)<= n到目标节点的距离实际值,这种情况下,搜索的点数多,搜索范围大,效率低。但能得到最优解。并且如果h(n)=d(n),即距离估计h(n)等于最短距离,那么搜索将严格沿着最短路径进行, 此时的搜索效率是最高的。
如果 估价值>实际值,搜索的点数少,搜索范围小,效率高,但不能保证得到最优解。

7. 求A到B之间的最短路径,怎么获取

问题:从某顶点出发,沿图的边到达另一顶点所经过的路径中,各边上权值之和最小的一条路径——最短路径。解决最短路的问题有以下算法,Dijkstra算法,Bellman-Ford算法,Floyd算法和SPFA算法,另外还有着名的启发式搜索算法A*,不过A*准备单独出一篇,其中Floyd算法可以求解任意两点间的最短路径的长度。任意一个最短路算法都是基于这样一个事实:从任意节点A到任意节点B的最短路径不外乎2种可能,1是直接从A到B,2是从A经过若干个节点到B。
(1) 迪杰斯特拉(Dijkstra)算法按路径长度(看下面表格的最后一行,就是next点)递增次序产生最短路径。先把V分成两组:
S:已求出最短路径的顶点的集合
V-S=T:尚未确定最短路径的顶点集合
将T中顶点按最短路径递增的次序加入到S中,依据:可以证明V0到T中顶点Vk的最短路径,或是从V0到Vk的直接路径的权值或是从V0经S中顶点到Vk的路径权值之和(反证法可证,说实话,真不明白哦)。
(2) 求最短路径步骤
初使时令 S={V0},T={其余顶点},T中顶点对应的距离值, 若存在<V0,Vi>,为<V0,Vi>弧上的权值(和SPFA初始化方式不同),若不存在<V0,Vi>,为Inf。
从T中选取一个其距离值为最小的顶点W(贪心体现在此处),加入S(注意不是直接从S集合中选取,理解这个对于理解vis数组的作用至关重要),对T中顶点的距离值进行修改:若加进W作中间顶点,从V0到Vi的距离值比不加W的路径要短,则修改此距离值(上面两个并列for循环,使用最小点更新)。
重复上述步骤,直到S中包含所有顶点,即S=V为止(说明最外层是除起点外的遍历)。

热点内容
安卓高级开发考什么 发布:2025-03-16 11:20:35 浏览:716
揽胜哪个配置带二代地形 发布:2025-03-16 11:16:52 浏览:969
c语言数组存储文件 发布:2025-03-16 11:16:48 浏览:788
sqlserver2016r 发布:2025-03-16 11:15:58 浏览:26
网页登录找不到该服务器什么意思 发布:2025-03-16 11:14:19 浏览:831
网站搭建服务器搭建 发布:2025-03-16 10:33:27 浏览:795
游戏目录在哪里安卓 发布:2025-03-16 10:33:19 浏览:467
婉儿脚本 发布:2025-03-16 10:19:33 浏览:580
c语言ftp下载文件 发布:2025-03-16 10:05:02 浏览:307
手机帐户密码怎么找回密码 发布:2025-03-16 10:02:10 浏览:706