迪杰斯特拉算法图解_寻路算法之迪杰斯特拉算法

迪杰斯特拉算法用于解决一个点到另一个点的寻路实现。已知有N个节点,以及节点之间的距离,来求其中一个节点到另一个节点的路径问题。

eb45c95ef5de9a423f5f50f0a2551a9e.png

在此算法中,有2个列表,close关闭列表和open开放列表。

close关闭列表:代表已经得到了起点到该列表中所有节点的最短路径

open开放列表:代表访问过,但是还没有加入到close列表中的元素列表集合;

算法流程:

1.将起点Start加入到close关闭列表中,并将起点设置为NewNode节点
2.遍历NewNode能到达的所有节点
   a.如果该节点未访问过,将该节点加入到open列表中,更新该点的距离和父节点;
   b.如果NewNode到该节点的距离小于老节点到达该节点的距离,更新该节点的距离和父节点;
3.选取open列表中,距离最短的一个点,设置为NewNode。将该节点加入到close列表中,并从open列表中删除
4.重复2-3,直到所有节点都加入到了close列表中。

最终就得到了起点到所有节点的最短路径,如果想打印详细路径,可以从终点根据父节点逆向查找。

详细演示过程:

1137c44dd269ca6a77d899662c48f652.png

根据如图,先构建出一个二维数组的有向图结构

int[,] map = new int[,] 
{
    {0,6,3,M,M,M},
    {M,0,M,5,M,M},
    {M,2,0,3,4,M},
    {M,M,M,0,2,3},
    {M,M,M,M,0,5},
    {M,M,M,M,M,0}
};

close 和 open 列表都为空

listClose = new List<Node>(); 
listOpen = new List<Node>(); 

e2c943050269ebf69bfd2b3d09811eef.png

1.根据有向图得到新节点1能到达的所有节点为 节点2和节点3,遍历该节点所有可达节点:

foreach 节点x  in  所有可达节点
{
    listOpen.Add(节点x);
    if( 起点到新节点的距离 + 新节点到节点x的距离 <  起点到节点x的距离  )
    {
        起点到节点x的距离 =  起点到新节点的距离 + 新节点到节点x的距离;
        节点x 的 父节点 更改为 新节点;
    }
}

2.找出open列表中,距离起点最短的节点

遍历open列表,可以找到最短的节点是节点3,
将节点3加入到close列表中,并从open列表中移除
可以将节点3作为新的节点,继续 操作1,直到找到了终点

节点1到节点3最近,将节点3作为新节点继续:

87c88ceb1384d7f75c4d8cee14856acd.png

节点3到节点2比节点1到节点2近,所以更新节点2的距离。

且open列表中,起点到节点2最近,将节点2加入close列表中

d323aa8f8e9b4fa261bb65b276bfb4b6.png

open列表中,起点到节点4最近,将节点4加入close列表中

open列表中,起点到节点5最近,将节点5加入close列表中

a119f267a28360822220740e005c48fc.png

open列表中,起点到节点6最近,将节点6加入close列表中

31b4b39423545d8b63fa9e244275f229.png

遍历结束,可以得到节点1到所有节点的最短距离以及路径

时间复杂度

从复杂度来看,主要是外层循环O(V)与内层循环(枚举v需要O(V),寻找最小的节点需要O(V))产生的,总复杂度为O(V*(V+V)) = O(V^2).

但其实Djikstra算法是可以优化到O(nlogn + m)的级别的 为什么?

因为必须把每个点都标记为已访问(即vis[i] = true),所以外层循环的O(V)时间是无法避免的 但是寻找最小的d[u]的过程可以不必要一个一个重新循环去寻找最小的那个的d[u] 可以通过堆优化来降低复杂度,最简单的做法就是直接用STL中的优先队列priority_queue(STL依赖症(划掉))

代码链接:

文档:迪杰斯特拉算法-代码.note

链接:有道云笔记

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值