Floyd算法,Dijkstra算法,Bellman算法,A*算法

任意两点最短路径:Floyd-WarShall

Floyd算法解决的问题是:对于任意两个节点st,求s到达t的最短路径

Floyd算法的思想是动态规划:

  • 定义d(i, j, k)为点i到点j之间,只允许借道节点1...k的最短路径;
  • 初始化:d(i,j,0) = e[i, j],即ij之间不经过任何其他中转节点的最短路径;
  • 更新dij的公式就是d(i, j, k) = min(d(i, j, k-1), d(i, k-1, k-1) + e[k, j])
  • 更新n次;

Floyd算法的时间复杂度是 O ( n 3 ) O(n^3) O(n3)

单源最短路径:Dijkstra

Dijkstra算法解决的问题是:没有负权边的情况下,从源节点s到其他任意节点t的路径长度

  • 维护一个dist数组,dist[i]表示si的最短距离;
  • 对于每个元素,标记是否其dist已经确定不需要再更改(或者说维护两个集合,一个集合的dist确定,另一个未确定);

Dijkstra算法是一种贪心策略:每次在未确定最短路径的节点里挑选距离s最近的那个点,把这个点标记为已经确定的dist,然后对从这个点出发的边进行松弛

为了标记每个点,使用一个bool数组表示:determined[i]true表示idist已经是最短路径,为false表示还不确定。

算法如下:

  • 初始化dist[i] = e[s, i]determined[i]false
  • dist未确定的元素里determined[i] == false中寻找一个dist最小的节点u
    • 标记udist已经确定determined[i] = true
    • u的所有出边进行松弛:si如果经过(u, i)这条边会不会变近?dist[i] = min(dist[i], dist[u] + e[u, i])
    • 重复循环直到所有的点都确定dist,重复N遍即可,每次只会确定一个新的节点的距离;

有负权边的单源最短路径:Bellman-Ford

Dijkstra算法的缺点在于不能处理边长为负数的情况,而这就是Bellman-Ford算法解决的

Bellman算法是一种动态规划算法(动态规划就是Bellman提出来的)。

  • 定义d(i, k)为源点si最多经过k条边的最短距离;
  • 初始化d(i, 1) = e[s, i]
  • 每次更新d的公式:for all(u, v): d(v, k) = min(d(v, k-1), d(u, k-1) + e[u, v])
  • 更新n-1次;

启发式搜索算法:A*

A*算法通过下面的函数来计算每个节点的优先级
f ( n ) = g ( n ) + h ( n ) f(n) = g(n) + h(n) f(n)=g(n)+h(n)
其中

  • f ( n ) f(n) f(n)是节点n的综合优先级,当我们选择下一个要遍历的节点时,总会选取综合优先级最高(值最小)的节点;
  • g ( n ) g(n) g(n)是节点n距离起点的代价;
  • h ( n ) h(n) h(n)是节点n距离终点的预计代价,就是A*算法的启发函数。

A*算法在运算过程中,每次从优先级队列中选取 f ( n ) f(n) f(n)值最小(优先级最高)的节点作为下一个待遍历的节点;A*算法使用两个集合来表示待遍历的节点与已经遍历过的节点;

A*算法的启发式函数一般分为三种:

  • 曼哈顿距离
  • 对角距离;
  • 欧几里得距离;

Dijkstra算法是A*算法的一个特例,其中所有节点的 h = 0 h=0 h=0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值