当前位置: 首页 > news >正文

谈谈数组和链表的时间复杂度

一、数组(Array)

数组是一块 连续的内存空间,元素紧挨着存放。

随机访问快 O(1)

  • 因为数组的地址是连续的,第 i 个元素的地址可以通过公式直接算出来:

    地址 = 起始地址 + i × 元素大小
    
  • 所以访问任意下标(比如 arr[1000])不需要遍历,直接跳到内存位置即可,耗时固定。

插入/删除慢 O(n)

  • 如果要在数组中间插入一个元素,比如在 arr[2] 插入 99:

    [10, 20, 30, 40, 50]↑ 插入 99
    

    那么 30, 40, 50 都要往后挪一位,才能空出位置。

  • 删除同理,要把后面的元素全部往前移,避免空洞。

  • 所以插入/删除需要移动 平均一半元素,最坏情况移动 n 个,复杂度 O(n)。


二、链表(Linked List)

链表的元素(节点)分散在内存中,每个节点都保存了 指向下一个节点的指针

插入/删除快 O(1)

  • 插入只需要改几个指针,不需要整体移动。
    例如在 20 和 30 之间插入 25:

    [20 | next] -> [30 | next]插入后:
    [20 | next] -> [25 | next] -> [30 | next]
    
  • 删除也类似,只要把前一个节点的指针指向下一个节点即可。

  • 这些操作和链表长度无关,所以是 O(1)。

随机访问慢 O(n)

  • 因为链表的节点不连续,不能直接算出第 i 个元素的地址。

  • 要找到第 i 个元素,必须从头节点开始,一个个沿着指针走,直到走到目标位置。

  • 所以平均需要访问 n/2 个节点,复杂度 O(n)。


三、总结对比

数据结构随机访问插入/删除
数组O(1) ✅O(n) ❌
链表O(n) ❌O(1) ✅

这里提出一个问题:链表插入一定比数组快吗?

答案是否定的:
之前说的 插入 O(1) 指的是:当你已经拿到插入位置的节点指针时,修改指针的操作本身是 O(1)


详细拆分:

假设链表是:

head -> [10] -> [20] -> [30] -> [40] -> [50] -> [60]

你要在 index=5 和 index=6 之间插入新节点 [55]

1. 定位位置 (O(n))

  • 你需要先遍历链表,找到第 5 个节点 [50]

  • 这一过程需要从头走一遍,最坏 O(n)。

2. 修改指针 (O(1))

  • 假设你已经有了第 5 个节点 [50] 的引用。

  • 插入操作只要改两条指针:

原来:
[50] -> [60]插入后:
[50] -> [55] -> [60]

这一步和链表长度无关,固定时间,所以是 O(1)。


那么为什么说链表插入是 O(1)?

这是一个 前提条件不同的问题:

  • 如果你只知道 index(比如第 5 个位置),那必须先遍历链表,整体复杂度 O(n)。

  • 如果你已经持有 要插入位置的节点引用(比如 [50] 这个节点对象),那插入动作就是 O(1)。

所以在算法书里常见的说法:

  • 数组:查找 O(1),插入 O(n)

  • 链表:查找 O(n),插入 O(1)

其实是各自强调了它们的优势场景。


类比理解

  • 数组像一排教室座位,要插人得全体后移,很麻烦

  • 链表像一串散开的手牵手的人,只要你站在第 5 个人旁边,就能很快把新朋友插进来。
    但如果你要找到第 5 个人,就得从头数过去,时间复杂度其实还是O(n)。

既然这样,那链表有什么优势呢?

链表真正的优势是在以下场景:

  1. 已知节点引用时的插入/删除

    • 例如有个指针 p 指向第 5 个节点,要在它后面插入/删除节点,只需改指针,O(1)。

    • 这在某些算法中很有用(比如 LRU 缓存,频繁在链表头尾插入/删除)。

  2. 动态扩展时更灵活

    • 数组扩容需要搬移到更大的一块连续内存,链表不需要。

  3. 频繁在头部/尾部插入删除

    • 单链表头部插入:O(1)

    • 双向链表尾部插入删除:O(1)

    • 对比数组头部插入/删除需要整体移动,效率差。

http://www.dtcms.com/a/399377.html

相关文章:

  • ServletContex读取properties文件,中文乱码
  • todesk取消客户端开机自动启动后,开机仍然会启动客户端,怎么设置?
  • C++编程学习(第36天)
  • 如何快速处理电脑上常常遇到的各种小问题?
  • 卷积神经网络(CNN)的LeNet模型
  • 佛山网站外包什么是网站推广方案
  • 合肥门户网站制作建设佛山cms建站
  • Linux命令大全-usermod命令
  • Linux网络HTTP协议(上)
  • 开源 java android app 开发(十四)自定义绘图控件--波形图
  • umijs 4.0学习 - umijs 的项目搭建+自动化eslint保存+项目结构
  • 汇天网络科技有限公司苏州关键词优化软件
  • 制冷剂中表压对应温度值的获取(Selenium)
  • 建什么网站访问量高seo优化
  • 小型网站建设参考文献word超链接网站怎样做
  • 可视化 GraphRAG 构建的知识图谱 空谈版
  • 安装gitlab并上传本地项目
  • 黄页88网站免费推广网站大全网
  • 深圳附近建站公司做企业网站有什么工作内容
  • 新能源知识库(104)什么是FAT和SAT?
  • 多元函数可微性的完整证明方法与理解
  • 长春建站培训wordpress广告先显示
  • 怎么做网页版手机版网站百度竞价托管公司
  • 【寰宇光锥舟】Bash 脚本详细解释
  • 如何高效解析复杂表格
  • glog使用: 07-错误信号处理(Failure Signal Handler)
  • Netty从0到1系列之内置Handler【下】
  • java服务注册到 Nacos 及相关配置
  • 设计网站与建设wordpress网站部署
  • 扬州鼎盛开发建设有限公司网站简单的ps网页设计教程