数组
Arrays
约 16 分钟 · v15
数组 Arrays
cs-ds/arrays · COMP1521/25211 一句话定义
数组就是内存里一排紧挨着、大小相同的格子。正因为它们连续又等宽,知道首地址就能一步算出第 i 个格子的地址:address = base + i × 每格字节数——所以 a[i] 是 O(1) 直达,不用从头数。
int 紧挨着排,每格 4 字节。第 i 格地址 = base + i×4——这条乘加公式就是「随机访问 O(1)」的全部秘密。2 模型 · 地址怎么算,代价在哪
分两小步:第 1 步用寻址探索器弄懂"第 i 格地址 = base + i×size"这条核心公式(这就是 O(1) 的来源);第 2 步看遍历 / 查找 / 插入的动画——访问单个是 O(1),但扫一遍或往中间插就是 O(n)。
首地址 base = 0x1000,每格 4 字节(一个 int)。输入下标 i,看它的地址怎么一步算出来、是哪一格
关键:算地址只用一次乘法 + 加法,跟数组多长、i 多大都没关系 → 这就是随机访问 O(1)。代码里 a[i] 编译器就是按 *(base + i*sizeof(元素)) 来取的。
声明时给定元素类型 + 个数,编译器就分配一整块连续内存;a[i] 与 *(a+i) 完全等价。
int a[8] = {10, 20, 35, 40, 55, 60}; // 8 格容量,先用 6 格 int n = 6; // 实际元素个数(容量≠个数!) // 取第 i 个:下面三种写法等价,都是 base + i*4 那一格 a[i]; *(a + i); i[a]; // (最后一种是 C 的冷知识)
数组名 a 在大多数场合退化成指向首元素的指针。所以传进函数后 sizeof(a) 量到的是指针大小、不再是整个数组——必须额外传长度 n。下面看三个操作的代价差别。
第 2 步 · 看三个操作。右边是真实 C 代码,随动画逐行高亮。重点感受:访问单格 O(1),但遍历、查找、往中间插入都要碰 n 个格子 = O(n)。点例子,再点 ▶(建议 0.5×)。
数组操作演示
3 核心要点 · 4 句人话看懂数组
每张卡片先用一句大白话说清"它到底在讲什么",再配最小例子。
a[i] 其实是 *(a+i)。数组传进函数后只剩一个首地址指针,长度信息丢了。sizeof(a) 在函数里量到的是指针大小(8)、不是数组总字节——必须额外传 n。4 错误实验室 · 点一下亲眼看 bug
下面 4 个是用数组最常翻车的坑——越界和「传参后 sizeof 失效」尤其爱考。点击卡片,控制台会模拟运行效果。
5 即时小测 · 5 题 + 动手例题
这 5 题都卡在初学者最常错的点上——地址公式、合法下标范围、各操作复杂度、sizeof 陷阱。最后到练习系统亲手写一遍数组遍历。
读完这节,你应该明白:
数组 = 内存里连续、等宽的一排格子。正因连续等宽,第 i 格地址 = base + i×sizeof 一步可算,所以 随机访问 a[i] 是 O(1)——这是它最大的优点。但反过来,在中间插入 / 删除要把后面元素整体搬移,是 O(n),而且容量通常固定。还有两个大坑:下标只能 0~n−1(越界即错),以及数组名传进函数会退化成指针、sizeof 失效,必须额外传长度 n。数组是排序、堆、哈希表、图邻接矩阵的底层地基;想要"中间插删也快",就轮到 链表 出场了 ↓