Dijkstra算法时间复杂度分析[通俗易懂]

Dijkstra算法时间复杂度分析[通俗易懂]文章目录Dijkstra算法的思路与关键点Dijkstra算法的时间复杂度之前一直默认Dijkstra算法时间复杂度为o(n2)o(n^{2})o(n2),没有思考过具体的时间复杂度,今天把这个弄清楚。Dijkstra算法的思路与关键点思路:广度优先+松弛所有点分为两个集合SSS和TTT,SSS最开始只包括源点sss,剩余点都位于TTT。SSS集合表示已经计算出最短路径的点集合,TTT表示尚未计算出最短路径的点集合。每次从集合TTT中选出一个与集合SSS距离最短的点vvv,将点vvv加

大家好,又见面了,我是你们的朋友全栈君。

之前一直默认Dijkstra算法时间复杂度为
o ( n 2 ) o(n^{2}) o(n2),没有思考过具体的时间复杂度,今天把这个弄清楚。

Dijkstra算法的思路与关键点

  • 思路:广度优先 + 松弛
  1. 所有点分为两个集合 S S S T T T S S S最开始只包括源点 s s s,剩余点都位于 T T T S S S集合表示已经计算出最短路径的点集合, T T T表示尚未计算出最短路径的点集合。
  2. 每次从集合 T T T中选出一个与集合 S S S距离最短的点 v v v,将点 v v v加入集合 S S S。通过点 v v v对集合 T T T中的点进行松弛,即更新 T T T中点的最短距离。
  3. 不断重复此步骤2,直至T集合中无法找出与集合 S S S相邻的点。
  • 关键点:每次从 T T T中选出的点,距离源点的距离一定不会被松弛,因此每次选出的点都将加入集合 S S S.。

Dijkstra算法的时间复杂度

设图中的节点数为 n n n,边个数为 m m m,平均每个点的边数 k = m / n k=m/n k=m/n

算法步骤2需要执行 n − 1 n-1 n1次,每次从集合 T T T中选出一个与集合 S S S相距最近的点,具体实现方式有4种。

  • 顺序遍历集合 T T T
  • 使用二叉堆作为优先队列
  • 使用二项堆作为优先队列
  • 使用斐波那契堆作为优先队列

前提知识:二叉堆,二项堆,斐波那契堆的各种操作时间复杂度
在这里插入图片描述

对于Dijkstra算法,给出时间复杂度的计算公式
( n − 1 ) ∗ ( T E X T R A C T − M I N + T D E L E T E + T D E C R E A S E − K E Y ∗ k ) (n-1)*(T_{EXTRACT-MIN}+T_{DELETE}+T_{DECREASE-KEY}*k) (n1)(TEXTRACTMIN+TDELETE+TDECREASEKEYk)

下面对于上述四种方式,分别计算其时间复杂度。

  1. 时 间 复 杂 度 = ( n − 1 ) ∗ ( T E X T R A C T − M I N + T D E L E T E + T D E C R E A S E − K E Y ∗ k ) = ( n − 1 ) ∗ ( n + 1 + k ) = n ∗ ( n + k ) = n 2 + m = n 2 \begin{aligned} 时间复杂度&=(n-1)*(T_{EXTRACT-MIN}+T_{DELETE}+T_{DECREASE-KEY}*k) \\ &=(n-1)*(n+1+k)\\ &=n*(n+k)\\ &=n^{2}+m &=n^{2} \end{aligned} =(n1)(TEXTRACTMIN+TDELETE+TDECREASEKEYk)=(n1)(n+1+k)=n(n+k)=n2+m=n2
  2. 时 间 复 杂 度 = ( n − 1 ) ∗ ( T E X T R A C T − M I N + T D E L E T E + T D E C R E A S E − K E Y ∗ k ) = ( n − 1 ) ∗ ( 1 + log ⁡ n + k ∗ log ⁡ ( n ) ) = n ∗ ( 1 + k ) log ⁡ n = ( n + m ) log ⁡ n \begin{aligned} 时间复杂度&=(n-1)*(T_{EXTRACT-MIN}+T_{DELETE}+T_{DECREASE-KEY}*k) \\ &=(n-1)*(1+\log{n}+k*\log(n))\\ &=n*(1+k)\log{n}\\ &=(n+m)\log{n} \end{aligned} =(n1)(TEXTRACTMIN+TDELETE+TDECREASEKEYk)=(n1)(1+logn+klog(n))=n(1+k)logn=(n+m)logn
  3. 时 间 复 杂 度 = ( n − 1 ) ∗ ( T E X T R A C T − M I N + T D E L E T E + T D E C R E A S E − K E Y ∗ k ) = ( n − 1 ) ∗ ( log ⁡ n + log ⁡ n + k ∗ log ⁡ ( n ) ) = n ∗ ( 2 + k ) log ⁡ n = ( 2 n + m ) log ⁡ n = ( n + m ) log ⁡ n \begin{aligned} 时间复杂度&=(n-1)*(T_{EXTRACT-MIN}+T_{DELETE}+T_{DECREASE-KEY}*k) \\ &=(n-1)*(\log{n}+\log{n}+k*\log(n))\\ &=n*(2+k)\log{n}\\ &=(2n+m)\log{n}\\ &=(n+m)\log{n} \end{aligned} =(n1)(TEXTRACTMIN+TDELETE+TDECREASEKEYk)=(n1)(logn+logn+klog(n))=n(2+k)logn=(2n+m)logn=(n+m)logn
  4. 时 间 复 杂 度 = ( n − 1 ) ∗ ( T E X T R A C T − M I N + T D E L E T E + T D E C R E A S E − K E Y ∗ k ) = ( n − 1 ) ∗ ( log ⁡ n + log ⁡ n + k ∗ 1 ) = n ∗ ( 2 log ⁡ n + k ) = 2 n log ⁡ n + m = n log ⁡ n + m \begin{aligned} 时间复杂度&=(n-1)*(T_{EXTRACT-MIN}+T_{DELETE}+T_{DECREASE-KEY}*k) \\ &=(n-1)*(\log{n}+\log{n}+k*1)\\ &=n*(2\log{n}+k)\\ &=2n\log{n}+m\\ &=n\log{n}+m\\ \end{aligned} =(n1)(TEXTRACTMIN+TDELETE+TDECREASEKEYk)=(n1)(logn+logn+k1)=n(2logn+k)=2nlogn+m=nlogn+m
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/146452.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 微信小程序swiper小程序轮播图小圆点样式修改

    微信小程序swiper小程序轮播图小圆点样式修改<swiperclass=”swiper-box”indicator-dots=”{{indicatordots}}”autoplay=”{{autoplay}}”><blockwx:for=”{{swiperItem}}”><swiper-item><navigatorurl=”{{item.linkUrl}}”><imageclass=

    2022年5月21日
    86
  • Linux文件之strstr函数、将一个整数,结构体和结构体数组写进文件里

    Linux文件之strstr函数、将一个整数,结构体和结构体数组写进文件里linux

    2022年8月31日
    3
  • 为什么你学不会递归?告别递归,谈谈我的经验[通俗易懂]

    为什么你学不会递归?告别递归,谈谈我的经验[通俗易懂]可能很多人在大一的时候,就已经接触了递归了,不过,我敢保证很多人初学者刚开始接触递归的时候,是一脸懵逼的,我当初也是,给我的感觉就是,递归太神奇了!可能也有一大部分人知道递归,也能看的懂递归,但在实际做题过程中,却不知道怎么使用,有时候还容易被递归给搞晕。也有好几个人来问我有没有快速掌握递归的捷径啊。说实话,哪来那么多捷径啊,不过,我还是想写一篇文章,谈谈我的一些经验,或许,能够给你带来一些帮助…

    2025年11月1日
    3
  • ping指定IP的指定端口_ping命令端口号多少

    ping指定IP的指定端口_ping命令端口号多少ping是简单的测试网络连接情况的小工具,对于一般用户很实用,但是ping有个缺点就是,不能指定端口tcping命令是针对tcp监控的,也可以看到ping值,即使源地址禁ping也可以通过tcpin

    2022年8月1日
    8
  • docker使用教程视频_docker到底怎么用

    docker使用教程视频_docker到底怎么用前言docker主要用于运维,当然了,开发也可以用,可以在启动应用项目的时候使用docker方式,docker是虚拟化技术,每一个docker容器都是一个linux虚拟机,而且还可以根据不同的应用定制,最小的可以直接依赖linux内核,仅仅几M就可以运行。下面,正式开始。 注意:如果是使用docker-compose方式,只看到第三的第6即可。 一、安装dockercent…

    2022年10月15日
    4
  • __nullable 消除

    __nullable 消除警告 Pointerismis 我觉得我是一个强迫症 写完代码都会去去掉所有的警告 有的我也去不掉好闹心 今天介绍一个警告的去掉方法 例子 刚刚遇见这个警告的时候脑子有点蒙 这是为什么呢 我觉得写法没什么问题的说 后来经过多番查找 发现这是 Xcode6 3 的一个新特性 即 nullabilitya

    2025年5月31日
    5

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号