dijkstra复杂度_优化的Dijkstra算法
优|化|的Dijkstra|算|法Dijkstra算法分析Dijkstra算法在课堂上老师已经详细讲解过,但是通过对算法分析我们可以发现有几点不足之处:(1)用邻接矩阵来存储网络图,其存储量为NxN。对于大型稀疏矩阵.这将耗费大量资源存储那些无意义的矩阵元素。(2)当从未标记节点集合选定下一个节点作中间节点后,在更新操作过程中,需要扫描所有的未标记节点并进行...
优|化|的
Dijkstra|算|法
Dijkstra
算法分析
Dijkstra算法在课堂上老师已经详细讲解过,但是通过对算法分析我们可以发现有几点不足之处:
(1)用邻接矩阵来存储网络图,其存储量为NxN。对于大型稀疏矩阵.这将耗费大量资源存储那些无意义的矩阵元素。
(2)当从未标记节点集合选定下一个节点作中间节点后,在更新操作过程中,需要扫描所有的未标记节点并进行比较更新。而未标记节点集合中往往包含大量与中间节点不直接相连的节点。
(3)在选择下一个最短路径 节点作为中间节点时,需要比较所有的未标记节点,而这个中间节点往往包含在与已标记节点集合的所有节点邻接的节点中。
(4)在算法的每次迭代中,由于未标记节点以无序的形式存放在一个链表中或一个数组中 ,每次选择最短路径节点都必须将所有未标记节点扫描一遍,当节 点数目很大时,这无疑将成为制约计算速度的关键因素。
堆优化的Dijkstra算法
针对Dijkstra算法存在的问题,最常用的优化算法是在数据的组织和存储以及最短路径节点的选取上进行改进。
优化思路分析
(1)数据组织和数据存储
对于海量的数据来说,用邻接矩阵存储图需要开辟NXN(N为节点数目)的存储空间,对于一个大型稀疏图来说,计算效率和存储效率都很低。所以可以采用邻接表来存储网络拓扑结构以节省存储空间。邻接表是图的一种链式存储结构,在邻接表中,节点元素保存在一个数组中。
(2)节点排序和最短路径节点的选取
在Dijkstra算法中,网络图中的每个节点均需实现从未标记节点到最短路径节点的转变.这种转变需要将大量的无序存储的未标记节点都扫描一遍,从中选取一个最短路径节点作为中间节点。在数据量大的情况下,必然会影响计算速度。解决此问题的最有效的方法就是把这些要扫描的节点按标号值进行排序,每循环一次就可取到符合条件的节点,这样就可以大大提高算法的执行效率。我们采用堆排序方法来选择最短路径节点。
在改进算法初始时,待排序的节点以无序形式连续存放在一个一维数组中,对其进行堆排序,调整成小顶堆后,各节点即是以完全二叉树的顺序存储结构形式存储,0号单元存放的即是调整后的堆顶元素,后面依次以左子树、右子树.在调整堆的过程中时间复杂度为0( logN).(N为待排序节点个数).与从无序结构下的数组或链表中选择下一个最短路径节点相比较,明显地节约了时间,提高算法执行效率。
优化算法基本原理
设置两个集合S和adj及一个数组T[ ],s 是已标记集合,adj是邻接点集,T[ ]存储待排序节点初始状态时,S={VO},T[ ] =adj[ VO],首先,将数组T[ ]通过堆排序调整为小顶堆,取数组首元即堆顶节点current为中间节点,并将current 加人到已标记集合S中;再次,比较更新current对邻接点集合与已标记集合的差集(Adj[ current] -S)中任一节点Vi的当前最短路径值;然后查找s集合所有节点的邻接点的并集与S集合的差集( Uadj[S]) -S),同时将这些节点顺次存人数组T中,覆盖原数组中的节点,并设置个计数器i记录节点个数;最后将数组中的前i个元素按它们当前的最短路径值调整成小顶堆,取堆顶节点为下一个最短路径节点将其归并到集合S中,如此反复迭代循环,直到所有的节点都加入到集s中。
复杂性分析与比较
空间复杂度分析
对于数据的存储传统的Dijkstra 算法采用图论中的邻接矩阵方法,其存储量为N xN(N为网络图中的节点数),通常的网络图尽管节点很多,但与节点相关联的节点数目并不多,一般都为稀疏图,这样该存储方法将浪费大量的空间,而且在计算时亦要花费大量的时间遍历无意义的数据.而改进算法采用了邻接表的链式存储结构,对于一个无向图来说,其存储量为0(E +2N)(E为节点列表中同节点关联的所有弧段数目).另外还使用了两个数组,其中一个数组D[ V]用来存储所求得源点到其它所有节点的最短路径值,另外一个数组T[ V]用来暂存待排序节点.所以总的空间复杂度为O(E +4N).与传统Dijkstra算法相比较,节省了空间,提高了存储效率。
时间复杂度分析
传统Dijkstra算法采用广度优先的搜索策略,在访问了网络中所有的节点后,最终生成从源点到其余各点的最短路径树.该算法在选择最短路径节点时需要访问所有的未标记节点,效率低下,整个算法的运行时间为O(N x N).而改进的Dijkstra算法的主要步骤在查找待排序节点和堆排序上,因待排序节点为所有已标记节点的邻居节点的并集与标记集合的差集,所以这个步骤的运行时间主要取决于已标记节点的邻节点集合元素数量的多少(而该数量值往往小于未标记集合中的元素个数),查找次数最多为E次.在排序过程中,每次调整的时间复杂度不会超过满二叉树的高度logN.这两个过程共需迭代执行N次,因此整个算法理论上最长运行时间仅为0( N(logN + E)).当网络拓扑结构图具有的节点数N较大且其关联矩阵为一个稀疏矩阵时,相对传统Dijkstra算法,优化算法大大减少了计算次数与比较次数,在一定程度上提高了运算速度.
传统Dijkstra算法使用的是邻接矩阵来存储网络图,存储量为N x N,而使用邻接表来存储网络数据信息,可使存储空间从NxN量级减少至N量级;既节省了存储空间又提高了运行效率。另外,利用堆排序来选择最短路径节点,只处理标记节点的相邻节点,从而大量减少了要计算的节点数,最终使得算法的时间复杂度由原来的0(N2)降至0(N( logN + E)).随着网络中节点数目和边数的增多,这种改进的Dijkstra算法越来越显示出其优势,可使算法所需的时间明显减少,并获得精度较高的结果。
其他几种
优化方法
权值排序优化策略
问题:未确定的最短路径的顶点无序存放在数组中,每一次选择权值最小的弧段必须将所有未选择顶点对应的数组元素完全扫描才能找到,在数据量较大的情况下,计算速度受到严重制约。
优化策略:
将要扫描的结点按其对应弧的权值进行顺序排列,每循环一次即可得到符合条件的结点,大大提高了算法的执行效率。
A*算法优化策略
问题:
Dijkstra算法基于广度优先搜索策略,即从源点出发,通过权值迭代遍历所有其他结点后,最后得到从源点到其他各结点的最短路径。整个搜索好似一个圆形向外展开,直到到达目的地,这样的搜索方式是盲目的。很明显这样求解一定能找到最优解,但节点展开的数量和距离成级数增加,会导致大量无效点的搜索,大大的降低搜索的效率。
优化策略:
采用改进的Dijkstra算法 A*算法。A*算法是人工智能运用在游戏中的一个重要实践,它主要是解决路径搜索问题。A*算法实际是一种启发式搜索。发表论文。所谓启发式搜索,就是利用一个估价函数judge()评估每次决策的价值,决定先尝试哪一种方案。这样可以极大地优化普通的广度优先搜索。从Dijkstra算法到A*算法是判断准则的引入,如果这个判断条件不成立,同样地,只能采用Dijkstra算法。这样能够大大降低搜索的效率。
扇形优化策略
问题:
Dijkstra算法的搜索过程好似以源点为圆心的一系列同心圆向外展开,搜索过程中没有考虑到终点所在方向或位置,搜索是盲目的。这样导致大量的无用临时结点被反复搜索,成为实际应用中的瓶颈。
优化策略:
从尽量减少最短路径分析过程中搜索的临时结点数量,限制范围搜索和限定方向搜索考虑进行优化。那么这种有损算法是否可行呢,我们知道,现实生活中行进,不会向着目的地的相反方向行进,否则就是南辕北辙。所以,当所研究的网络可以抽象化为平面网络的条件下,也不必搜索全部结点,可以在以源点到终点所在直线为轴线的扇形区域内搜索最短路径。这样,搜索方向明显地趋向终点,提高了搜索速度,虽然抛弃了部分结点,但基本上不影响搜索的成功率。
邻接点优化策略
问题:
Dijkstra算法在提取最短路径结点时需要访问所有的未确定最短路径的结点,即使只希望找到从源点到某一特定的终点的最短路径也不例外。结点数n越大,算法的计算效率和存储效率越低。
优化策略:
只对最短路径上结点的邻接点作处理,不涉及其他结点。即
(1) 只从源点的邻接点集合中选择权值最小的结点作为转接点,将此转接点加入已确定最短路径的结点集合S中;
(2)对此转接点的邻接点集合与S的差集中的结点的权值进行更新;
(3)从S中所有结点的邻接点集合的并集与S的差集中选择权值最小的结点作为下一个转接点,并将此转接点加入S中。重复(2), (3)操作,直至所有的结点确定最短路径。优化算法在更新最短路径值与选择最短路径值最小的结点时,仅仅涉及相关结点的邻接点集合及S集合中所有结点的邻接点集合与S集合的差集,时间复杂度取决于转接点的邻接点的数量多少,减少了计算次数与比较次数。
- END -
欢迎关注我们~
计算机网络翻转课堂
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐

所有评论(0)