在搬运之前 onenote 里面的笔记,这里补一篇迪杰斯特拉算法图解,也当作复习一下。
算法步骤
- 每次从未标志节点中选择距离起点最近的节点,然后标志已检查;
- 计算刚标志的节点 A 到未标志的邻近节点 B 的距离,若节点 A 的距离 a +节点 A 到节点 B 的距离 ab < 节点 B 的距离 b。更新节点 B 的距离 b=a+ab,更新节点 B 的路径父节点为节点 A;
- 检查完所有节点,从目标节点的父节点往前遍历,便得到起点到终点的最短路径;
图解
标志列表:记录检查过的节点。
距离列表:记录节点到起点的最短距离,初始化全是无穷大。
父节点列表:记录节点的最短距离路径父节点。
在图示中,水平和纵向栅格移动代价为 2,斜向代价为 3。绿色栅格表示起始节点,紫色栅格表示障碍物,红色栅格表示目标节点。
迭代 0 :初始化,标志列表为空,距离列表记录的距离为无穷大,父节点列表各节点父节点为空。
在初始化后,需要先更新起始节点的距离信息为 0。
迭代 1 :在未标志的节点中,起始节点 00 的距离信息最小。
- 标志离起始节点最近的节点,也就是起始节点 00 本身。
- 更新附近节点 01,05,06 的距离信息,再更新其父节点为节点 00。
迭代 2 :在未标志的节点中,节点 01 和节点 05 距离信息最小,都是 2。
- 按下标顺序,先标志节点 01。
- 更新节点 01 附近节点 00,02,05,06,07 的距离信息。
- 其中节点 00 已经标志过了,不需要更新。
- 节点 02,07 被障碍物占据,距离信息仍是无穷大。
- 节点 05 距离信息 (d05=2) < 节点 01 距离 (d01=2) + 节点间距离 (d0105=3) 的距离,节点 05 距离信息不更新。
- 节点 06 距离信息 (d06=3) < 节点 01 距离 (d01=2) + 节点间距离 (d0106=2) 的距离,节点 06 距离信息不更新。
- 距离信息没有更新,父节点也不需要更新。
迭代 3 :在未标志的节点中,节点 05 距离信息最小。
- 标志节点 05。
- 更新节点 05 附近节点 00,01,06,10,11 的距离信息。
- 其中节点 00,01 已经标志过了,不需要更新。
- 节点 06 距离信息 (d06=3) < 节点 05 距离 (d05=2) + 节点间距离 (d0506=2) 的距离,节点 05 距离信息不更新。
- 节点 10 距离信息 d10 更新为节点 05 距离 (d05=2) + 节点间距离 (d0510=2) = 4。
- 节点 11 距离信息 d11 更新为节点 05 距离 (d05=2) + 节点间距离 (d0511=3) = 5。
- 更新节点 10,11 父节点为节点 05。
迭代 4 :在未标志的节点中,节点 06 距离信息最小。
- 标志节点 06。
- 更新节点 06 附近节点 00,01,02,05,07,10,11,12 的距离信息。
- 其中节点 00,01,05 已经标志过了,不需要更新。
- 节点 02,07 被障碍物占据,距离信息仍是无穷大。
- 节点 10 距离信息 (d10=4) < 节点 06 距离 (d06=3) + 节点间距离 (d0610=3) 的距离,节点 10 距离信息不更新。
- 节点 11 距离信息 (d11=5) = 节点 06 距离 (d06=3) + 节点间距离 (d0611=2) 的距离,节点 11 距离信息不更新。
- 节点 12 距离信息 d12 更新为节点 06 距离 (d06=3) + 节点间距离 (d0612=3) = 6。
- 更新节点 12 父节点为节点 06。
迭代 5 :在未标志的节点中,节点 10 距离信息最小。
- 标志节点 10。
- 更新节点 10 附近节点 05,06,11 的距离信息。
- 其中节点 05,06 已经标志过了,不需要更新。
- 节点 11 距离信息 (d11=5) < 节点 10 距离 (d10=4) + 节点间距离 (d1011=2) 的距离,节点 11 距离信息不更新。
- 距离信息没有更新,父节点也不需要更新。
迭代 6 :在未标志的节点中,节点 11 距离信息最小。
- 标志节点 11。
- 更新节点 11 附近节点 05,06,07,10,12 的距离信息。
- 其中节点 05,06 ,10 已经标志过了,不需要更新。
- 节点 07 被障碍物占据,距离信息仍是无穷大。
- 节点 12 距离信息 (d12=6) < 节点 11 距离 (d11=5) + 节点间距离 (d1112=2) 的距离,节点 12 距离信息不更新。
- 距离信息没有更新,父节点也不需要更新。
迭代 7 :在未标志的节点中,节点 12 距离信息最小。
- 标志节点 12。
- 更新节点 12 附近节点 06,07,08,11,13 的距离信息。
- 其中节点 06 ,11 已经标志过了,不需要更新。
- 节点 07 被障碍物占据,距离信息仍是无穷大。
- 节点 08 距离信息 d08 更新为节点 12 距离 (d12=6) + 节点间距离 (d1208=3) = 9。
- 节点 13 距离信息 d13 更新为节点 12 距离 (d12=6) + 节点间距离 (d1213=2) = 8。
- 更新节点 08,13 父节点为节点 12。
迭代 8 :在未标志的节点中,节点 13 距离信息最小。
- 标志节点 13。
- 更新节点 13 附近节点 07,08,09,12,14 的距离信息。
- 其中节点 12 已经标志过了,不需要更新。
- 节点 07 被障碍物占据,距离信息仍是无穷大。
- 节点 08 距离信息 (d08=9) < 节点 13 距离 (d13=8) + 节点间距离 (d1308=2) 的距离,节点 08 距离信息不更新。
- 节点 09 距离信息 d09 更新为节点 13 距离 (d13=8) + 节点间距离 (d1309=3) = 11。
- 节点 14 距离信息 d14 更新为节点 13 距离 (d13=8) + 节点间距离 (d1314=2) = 10。
- 更新节点 09,14 父节点为节点 13。
迭代 9 :在未标志的节点中,节点 08 距离信息最小。
- 标志节点 08。
- 更新节点 08 附近节点 02,03,04,07,09,12,13,14 的距离信息。
- 其中节点 12,13 已经标志过了,不需要更新。
- 节点 02,07 被障碍物占据,距离信息仍是无穷大。
- 节点 09 距离信息 (d09=11) = 节点 08 距离 (d08=9) + 节点间距离 (d0809=2) 的距离,节点 09 距离信息不更新。
- 节点 14 距离信息 (d14=10) < 节点 08 距离 (d08=9) + 节点间距离 (d0814=3) 的距离,节点 14 距离信息不更新。
- 节点 03 距离信息 d03 更新为节点 08 距离 (d08=9) + 节点间距离 (d0803=2) = 11。
- 节点 04 距离信息 d04 更新为节点 08 距离 (d08=9) + 节点间距离 (d0804=3) = 12。
- 更新节点 03,04 父节点为节点 08。
迭代 10 :在未标志的节点中,节点 14 距离信息最小。
- 标志节点 14。
- 更新节点 14 附近节点 08,09,13 的距离信息。
- 其中节点 08,13 已经标志过了,不需要更新。
- 节点 09 距离信息 (d09=11) = 节点 14 距离 (d14=10) + 节点间距离 (d1409=2) 的距离,节点 09 距离信息不更新。
- 距离信息没有更新,父节点也不需要更新。
迭代 11 :在未标志的节点中,节点 03,09 距离信息最小。
- 按下标顺序,先标志节点 03。
- 更新节点 03 附近节点 02,04,07,08,09 的距离信息。
- 其中节点 08 已经标志过了,不需要更新。
- 节点 02,07 被障碍物占据,距离信息仍是无穷大。
- 节点 04 距离信息 (d04=12) < 节点 03 距离 (d03=11) + 节点间距离 (d0304=2) 的距离,节点 04 距离信息不更新。
- 节点 09 距离信息 (d09=11) < 节点 03 距离 (d03=11) + 节点间距离 (d0309=3) 的距离,节点 09 距离信息不更新。
- 距离信息没有更新,父节点也不需要更新。
迭代 12 :在未标志的节点中,节点 09 距离信息最小。
- 标志节点 09。
- 更新节点 09 附近节点 03,04,08,13,14 的距离信息。
- 其中节点 03,08,13,14 已经标志过了,不需要更新。
- 节点 04 距离信息 (d04=12) < 节点 09 距离 (d09=11) + 节点间距离 (d0904=2) 的距离,节点 04 距离信息不更新。
- 距离信息没有更新,父节点也不需要更新。
此时已经标志了目标节点 09 了!目标节点的最短路径已经检查结束!
在父节点列表中,从节点 09 的父节点往前遍历,得到 09 -> 13 -> 12 -> 06 -> 00 的最短路径。
迭代 13 :在未标志的节点中,节点 04 距离信息最小。
- 标志节点 04。
- 更新节点 04 附近节点 03,08,09 的距离信息。
- 其中节点 03,08,09 已经标志过了,不需要更新。
- 距离信息没有更新,父节点也不需要更新。
最后剩下的未标志节点都是障碍物。全地图遍历结束,从起始节点到地图任意可达节点的最短路径都获得了。
思考
- 节点距离概念泛化
迪杰斯特拉算法中,节点的距离不仅可以看作是欧氏距离,还可以看作是移动成本。例如给地图增加障碍物距离信息,节点离障碍物越近,移动成本越大。这样迪杰斯特拉算法遍历搜索的得到路径就不是最短路径,而是移动成本最低的路径,路径离障碍物距离得当且距离相对较短。
- 一定要遍历完所有节点吗?
当“未标记节点中距离起点最近的点”中存在目标点,例如图解的迭代 11,此时就可以直接标志目标节点,得到目标最短路径了。