a算法dijkstra
⑴ 最短路径问题5种类型
最短路径问题5种类型有Dijkstra算法、A*算法、SPFA算法、Bellman-Ford算法和Floyd-Warshall算法,
扩展知识:
用于解决最短路径问题的算法被称做“最短路径算法”,有时被简称作“路径算法”。最常用的路径算法有:
Dijkstra算法、A*算法、SPFA算法、Bellman-Ford算法和Floyd-Warshall算法,本文主要介绍其中的三种。
最短路径问题是图论研究中的一个经典算法问题,旨在寻找图(由结点和路径组成的)中两结点之间的最短路径。
算法具体的形式包括:确定起点的最短路径问题:即已知起始结点,求最短路径的问题。
确定终点的最短路径问题:与确定起点的问题相反,该问题是已知终结结点,求最短路径的问题。在无向图中该问题与确定起点的问题完全等同,在有向图中该问题等同于把所有路径方向反转的确定起点的问题。
确定起点终点的最短路径问题:即已知起点和终点,求两结点之间的最短路径。
⑵ 图遍历算法之最短路径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/
⑶ 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
⑷ A*算法 和 最佳优先搜索算法(Best-First-Search)
最佳优先搜索算法是一种启发式搜索算法(Heuristic Algorithm),其基于广度优先搜索算法,不同点是其依赖于估价函数对将要遍历的节点进行估价,选择代价小的节点进行遍历,直到找到目标点为止。 BFS算法不能保证找到的路径是一条最短路径,但是其计算过程相对于Dijkstra
算法会快很多 。
最佳优先搜索是一种启发式搜索算法。广度优先搜索和深度优先搜索都属于穷举类型的搜索,需要依次遍历所有的节点,当空间非常大的时候,这种方式的效率就会非常差。而启发式的搜索是对状态控件中的每个点进行评估,然后选出最好的位置。
启发估价函数公式为:
n表示当前的点,g(n)为从起始点到点n的实际代价,h(n)为从点n到目标点的估价。
(图片来源于网络)
A*算法将BFS算法和Dijkstra算法结合在一起,结合两算法的优点,既可以查找最短路径的,有拥有和BFS差不多的效率。
(图片来源于网络)
A*算法详解
模拟寻路的地址
⑸ a*算法求最短路径和floyd还有dijsktra算法求最短路径的区别
A*算法是启发式搜索,适合点对点的最短路径,单源单汇的情况
Floyd是动态规划的一种,可以求出任意两点之间的最短路径
Dijkstra是贪婪算法的一种,求一点到其他所有点的最短路,即所谓的单源最短路算法
从时间复杂度来说
Floyd是O(N^3)
Dijkstra是O(N^2)
而启发式搜索就不好说了……
结果当然是一样的,都是最短路,但是适用情形和时空开销就不同了
举例来说,你做任意两点间最短路可以用N次Dijkstra或者1次Floyd,时间消耗一样,显然用后者,而如果你只用求两点间的,用Floyd就不合算了
⑹ 最短路径算法(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题
⑺ A*算法(启发式算法)
A*算法
这是我写的第一篇有关A*算法的文章,写得比较简洁,我决定再写一篇,补充一下对A*算法的理解。
A*算法把 Dijkstra算法 (靠近初始点的结点)和 BFS算法 (靠近目标点的结点)的信息块结合起来。
g(n)表示从初始结点到任意结点n的实际代价
h(n)表示从结点n到目标点的启发式评估代价
(1)h(n)=0,一种极端情况
如果h(n)=0,则只有g(n)起作用,此时A*演变成Dijkstra算法,这保证能找到最短路径,但效率不到,因为得不到启发。
(2)h(n)<实际代价
如果h(n)经常都比从n移动到目标的实际代价小(或者相等),则A*保证能找到一条最短路径。h(n)越小,A*扩展的结点越多,运行就越慢。
(3)h(n)=实际代价
如果h(n)精确地等于从n移动到目标的实际代价,则A*将会仅仅寻找最佳路径而不扩展别的任何结点,这会运行得非常快。尽管这不可能在所有情况下发生,你仍可以在一些特殊情况下让它们精确地相等(指让h(n)精确地等于实际代价)。只要提供完美的信息,A*就会运行得很完美。
(4)h(n)>实际代价
如果h(n)有时比从n移动到目标的实际代价大,则A*不能保证找到一条最短路径,但它运行得更快。
(5)h(n)>>实际代价(>>远大于),另一种极端情况
如果h(n)比g(n)大很多,则只有h(n)起作用,A*演变成BFS算法。
数组?链表?
在Open集上主要有三种操作:查找优先级最高的结点&删除结点、查找相邻结点是否在集合中、插入新结点
在Close集上主要有两种操作:查找相邻结点是否在集合中、插入新节点
(1)未排序数组或链表
最简单的数据结构是未排序数组或链表。查找结点,花费O(N);插入结点,花费O(1);删除结点,花费O(N)
(2)排序数组
为了加快删除操作,可以对数组进行排序。查找结点,变成O(logN),因为可以使用折半查找;插入结点,花费O(N);查找和删除优先级最高的结点,花费O(1)
(3)排序链表
在排序数组中,插入操作很慢。如果使用链表则可以加速该操作。查找结点,花费O(N);插入结点,花费O(1),但查找插入位置,需要花费O(N)
(4)哈希表
使用哈希表,查找结点,花费O(1);插入结点,花费O(1);查找和删除优先级最高的结点,花费O(N)
https://blog.csdn.net/coutamg/article/details/53923717#!/_alzvzu0wsphb4nstr5bbro1or