hello算法笔记 02
很久没更新算法学习,打算这个栏目至少要一周4更以上了,算法是一切的基础。虽说实际开发时要自己手敲的算法不是很多,模型什么都在,但至少面试什么的要能过,leetcode hot100 差不多都能写完。
1 数组与链表重点回顾
重点回顾
- 数组和链表是两种基本的数据结构,分别代表数据在计算机内存中的两种存储方式:连续空间存储和分散空间存储。两者的特点呈现出互补的特性。
- 数组支持随机访问、占用内存较少;但插入和删除元素效率低,且初始化后长度不可变。
- 链表通过更改引用(指针)实现高效的节点插入与删除,且可以灵活调整长度;但节点访问效率低、占用内存较多。常见的链表类型包括单向链表、环形链表、双向链表。
- 列表是一种支持增删查改的元素有序集合,通常基于动态数组实现。它保留了数组的优势,同时可以灵活调整长度。
- 列表的出现大幅提高了数组的实用性,但可能导致部分内存空间浪费。
- 程序运行时,数据主要存储在内存中。数组可提供更高的内存空间效率,而链表则在内存使用上更加灵活。
- 缓存通过缓存行、预取机制以及空间局部性和时间局部性等数据加载机制,为 CPU 提供快速数据访问,显著提升程序的执行效率。
- 由于数组具有更高的缓存命中率,因此它通常比链表更高效。在选择数据结构时,应根据具体需求和场景做出恰当选择。
2 队列底层实现
【队列的底层逻辑是数组或者链表吗?】
队列的底层实现可以是数组,也可以是链表,两种方式各有特点:
基于数组的实现:
- 通常使用固定大小的数组或动态数组(如 Python 的 list)
- 需要维护队头和队尾指针(索引)
- 可能存在 "假溢出" 问题(数组未满但无法插入新元素),解决方法是使用循环队列
- 随机访问效率高,但插入删除操作在队头时效率较低(需要移动元素)
基于链表的实现:
- 使用单链表或双向链表
- 同样需要维护队头和队尾指针
- 不存在固定大小限制,内存利用率更高
- 插入删除操作效率高(只需调整指针),但随机访问效率低
在实际应用中,两种实现方式都很常见:
- 当队列大小可预测且需要高效随机访问时,数组实现更合适
- 当队列大小不确定且频繁进行插入删除操作时,链表实现更有优势
许多编程语言的标准库队列实现会根据具体场景选择合适的底层结构,有些甚至会结合两者的优点进行优化。
3 硬盘、内存、缓存
【硬盘是存放长期静态的文件,内存是动态的短期的,缓存是为运行当前文件实时加载的吗?】
你的理解基本准确,但需要更精准地补充细节,尤其是 “缓存” 的定位 —— 它并非仅为 “当前文件实时加载”,而是多级存储体系中用于衔接速度差异、提升整体效率的 “高速缓冲层”。下面从 “存储层级逻辑” 和 “三者核心差异” 两方面展开,帮你理清底层关系:
一、先明确核心认知:三者是 “多级存储体系” 的不同层级
计算机设计的核心逻辑之一是 “用速度换容量,用容量换成本”—— 速度越快的存储,容量越小、成本越高。硬盘、内存、缓存(这里默认指 CPU 缓存,是最关键的缓存层级)正是按 “速度从慢到快、容量从大到小、成本从低到高” 排列的三级存储,职责是协同工作而非孤立存在:
- 硬盘(长期存储层):负责 “永久保存” 数据,即使断电也不丢失,是所有数据的 “源头仓库”(比如你的文档、软件安装包、操作系统文件)。
- 内存(短期运行层):负责 “临时加载” 硬盘中需要当前运行的数据 / 程序(比如你打开的 Excel、正在播放的视频),因为硬盘速度太慢,无法直接支撑 CPU 的高速运算 ——CPU 要处理数据,必须先把硬盘里的内容 “搬到内存”,断电后内存数据会丢失。
- 缓存(高速缓冲层):负责 “衔接 CPU 与内存的速度差”——CPU 运算速度极快(每秒数十亿次),内存速度虽比硬盘快(约 100-1000 倍),但仍跟不上 CPU。因此缓存会把内存中 “CPU 最常访问的数据 / 指令”(比如循环代码、频繁使用的变量)提前加载进来,让 CPU 直接从缓存取数据,避免频繁等待内存,大幅提升效率。
二、硬盘、内存、缓存的核心差异对比
为了更清晰区分,我们用表格总结关键维度:
对比维度 | 硬盘(HDD/SSD) | 内存(RAM) | 缓存(CPU Cache,如 L1/L2/L3) |
---|---|---|---|
存储性质 | 永久性存储(断电数据不丢) | 临时性存储(断电数据丢失) | 超临时性存储(断电数据丢失) |
核心作用 | 长期保存所有数据 / 程序(仓库) | 临时加载 “当前运行” 的数据 / 程序 | 缓存 “CPU 最常访问” 的数据 / 指令 |
速度 | 最慢(HDD 约 100-200MB/s;SSD 约 1-5GB/s) | 较快(约 10-50GB/s) | 最快(约 100-1000GB/s,接近 CPU 速度) |
容量 | 最大(通常 TB 级,如 1TB/2TB/4TB) | 中等(通常 GB 级,如 8GB/16GB/32GB) | 最小(通常 MB 级,如 L3 缓存 16MB/32MB) |
成本 | 最低(每 GB 几分到几角钱) | 中等(每 GB 几元到十几元) | 最高(每 GB 几十到几百元) |
访问逻辑 | 按 “文件系统路径” 访问(如 C:/ 文档 /xxx.doc) | 按 “内存地址” 直接访问(CPU 通过地址找数据) | 按 “局部性原理” 主动缓存(优先存 CPU 近期会用的数据) |
三、补充 2 个关键误区修正
“缓存仅为当前文件加载” 是片面的
缓存的核心逻辑是 “局部性原理”——CPU 访问数据时,通常会 “近期反复访问同一数据”(如循环变量)或 “访问相邻数据”(如数组)。因此缓存不仅加载 “当前文件”,还会根据访问规律,提前缓存 “可能即将用到的数据”(比如你正在编辑的文档,缓存会提前加载文档的下一段内容,而不只是当前显示的段落)。“内存是动态的” 需要更精准理解
内存的 “动态” 体现在两方面:- 数据动态替换:当你关闭一个程序(如 Excel),系统会释放它占用的内存,分配给新打开的程序(如浏览器);
- 数据实时更新:内存中的数据会随程序运行实时修改(比如你在 Excel 中输入数字,内存中对应的单元格数据会立即更新),而硬盘中的数据需要主动 “保存” 才会更新(如按 Ctrl+S)。
总结
简单来说,三者的关系像 “家庭仓库→客厅桌子→手边托盘”:
- 硬盘是 “仓库”,长期放所有东西(换季衣服、备用物品);
- 内存是 “客厅桌子”,临时放你当前要用的东西(正在吃的零食、看的书);
- 缓存是 “手边托盘”,放你 “马上要用到” 的小物件(比如手里正在剥的糖、翻书的书签),让你不用频繁起身去桌子 / 仓库拿,效率更高。