数据结构从入门到精通二 ~ 数组和链表

1. 前言

在计算机科学和软件工程领域,数据结构是指在计算机中组织和存储数据的方式,数组和链表是其中最基础也是最常用的两种数据结构之一。

  • 数组(Array):是一种线性表数据结构,它使用连续的内存空间来存储一组相同类型的数据。数组提供了快速随机访问元素的能力,但插入和删除操作可能比较耗时,因为需要移动大量元素。

  • 链表(Linked List):也是一种线性表数据结构,但不同于数组,链表中的元素(节点)通过指针相互连接。每个节点包含数据和指向下一个节点的指针。链表支持快速插入和删除操作,但访问特定位置的元素时需要从头开始遍历,效率较低。

2. 内存结构

数组和链表这两种基础且重要的数据结构,它们分别代表了"连续存储"和"分散存储"两种物理结构。

物理结构在很大程度上决定了程序对内存和缓存的使用效率,进而影响算法程序的整体性能。

  1. 硬盘用于长期存储大量数据
  2. 内存用于临时存储程序运行中正在处理的数据
  3. 缓存则用于存储经常访问的数据和指令

内存是有限的,且同一块内存不能被多个程序共享,因此我们希望数据结构能够尽可能高效地利用空间。数组的元素紧密排列,不需要额外的空间来存储链表节点间的引用(指针),因此空间效率更高。然而,数组需要一次性分配足够的连续内存空间,这可能导致内存浪费,数组扩容也需要额外的时间和空间成本。

链表以"节点"为单位进行动态内存分配和回收,提供了更大的灵活性。

另一方面,在程序运行时,随着反复申请与释放内存,空闲内存的碎片化程度会越来越高,从而导致内存的利用效率降低。数组由于其连续的存储方式,相对不容易导致内存碎片化。相反,链表的元素是分散存储的,在频繁的插入与删除操作中,更容易导致内存碎片化。

"缓存未命中"越少,CPU 读写数据的效率就越高。

缓存的容量有限,只能存储一小部分频繁访问的数据,因此当 CPU 尝试访问的数据不在缓存中时,就会发生缓存未命中(cache miss),此时 CPU 不得不从速度较慢的内存中加载所需数据。

  1. 占用空间:链表元素比数组元素占用空间更多,导致缓存中容纳的有效数据量更少。
  2. 缓存行:链表数据分散在内存各处,而缓存是"按行加载"的,因此加载到无效数据的比例更高。
  3. 空间局部性:数组被存储在集中的内存空间中,因此被加载数据附近的数据更有可能即将被访问。

数组具有更高的缓存命中率,因此它在操作效率上通常优于链表。

如果数据量非常大、动态性很高、栈的预期大小难以估计,那么基于链表实现的栈更加合适。链表能够将大量数据分散存储于内存的不同部分,并且避免了数组扩容产生的额外开销。

程序运行时,数据主要存储在内存中。数组可提供更高的内存空间效率,而链表则在内存使用上更加灵活。

数组灵活性:栈上的数组的大小需要在编译时确定,而堆上的数组的大小可以在运行时动态确定。

数组实现额外支持随机访问,但这已超出了栈的定义范畴,因此一般不会用到。效率并不高。

相关推荐
范什么特西24 分钟前
计算机杂记
java
RyFit32 分钟前
SpirngAI
java
庞轩px38 分钟前
第六篇:Spring用了哪些设计模式?——从单例到代理,拆解框架中的经典设计
java·spring·设计模式·bean·代理模式·aop·单例
番石榴AI1 小时前
纯 CPU 推理!0.1B 超轻量级端到端OCR模型,使用 Java 进行文档解析
java·开发语言·ocr
likerhood1 小时前
ConcurrentHashMap详细讲解(java)
java·开发语言·性能优化
naturerun2 小时前
从数组中删除元素的算法
数据结构·c++·算法
源码集结号2 小时前
基于 Spring Boot + JPA + MySQL的上门家政系统代码示例
java·前端·后端
程序员老邢3 小时前
【技术底稿 32】Nginx 经典大坑复盘:本机公网域名自环代理,导致接口返回首页 / 404 实战排障
java·运维·nginx·前后端分离·技术底稿·后端部署
该昵称用户已存在3 小时前
从成本中心到价值引擎:MyEMS 开源系统激活企业能源数据资产
java·后端·struts