数组

  • 什么是数组
  • 内存中的存储方式
  • 随机访问
  • 添加和删除数据
  • 时间复杂度
  • 数组与链表的对比

什么是数组

数组是一种数据呈线性排列的数据结构。你可以把它想象成电影院里一排连续的座位——每个座位都有编号(索引),从 0 开始,座位之间没有空隙。

索引:   0      1      2      3      4
      ┌──────┬──────┬──────┬──────┬──────┐
数据:  │ Blue │Yellow│ Red  │Green │ Pink │
      └──────┴──────┴──────┴──────┴──────┘
       ↑
    a[0] 就是第一个元素

数组最大的特点是:数据按顺序存储在内存的连续空间内

内存中的存储方式

计算机内存就像一大堆带地址的抽屉。数组在申请内存时,会一次性申请一块连续的空间,所有元素紧挨着存放。

内存地址:  100   101   102   103   104
         ┌─────┬─────┬─────┬─────┬─────┐
         │  10  │  20  │  30  │  40  │  50  │
         └─────┴─────┴─────┴─────┴─────┘
           ↑
       a[0] 在地址 100
       a[1] 在地址 101 (= 100 + 1个元素的大小)
       a[2] 在地址 102 (= 100 + 2个元素的大小)

因为元素是连续存放的,所以只要知道数组起始地址和元素大小,就能直接算出任意元素的地址——这就是随机访问(Random Access)的基础。

随机访问

想访问第 3 个元素?直接用 a[2] 就行,不需要从头遍历。不管数组有 10 个元素还是 1000 万个元素,访问任意一个元素的时间都是固定的。

a = [10, 20, 30, 40, 50]
print(a[2])   # 输出 30,一步到位
print(a[4])   # 输出 50,同样一步到位

添加和删除数据

数组的添加和删除比较麻烦,因为要保持元素的连续性。

在中间插入元素(比如在第 2 个位置插入 Green):

插入前:  Blue  Yellow  Red  Pink
                    ↓ 要在这里插入 Green

步骤1: 末尾申请空间
        Blue  Yellow  Red  Pink   _

步骤2: 把 Red 往后移
        Blue  Yellow  _    Red  Pink

步骤3: 把 Yellow 往后移(哦不,Yellow 留着)
        Blue  Yellow  _    Red  Pink

步骤4: 在空位写入 Green
        Blue  Yellow  Green  Red  Pink

删除元素反过来:先删掉目标,然后把后面的元素一个个往前移。

时间复杂度

操作 时间复杂度 说明
访问(读取) O(1) 通过下标直接算出地址
查找(搜索) O(n) 需要逐个比较(无序数组)
在末尾插入 O(1) 直接放在最后
在头部/中间插入 O(n) 需要移动后面所有元素
在头部/中间删除 O(n) 需要移动后面所有元素

数组与链表的对比

操作 数组 链表
读取/访问 O(1) 快 O(n) 慢
插入 O(n) 慢 O(1) 快
删除 O(n) 慢 O(1) 快
内存 连续空间 分散存储

选择建议

  • 如果需要频繁随机访问(如通过索引读取元素),用数组
  • 如果需要频繁插入和删除(如在头部添加元素),用链表
  • 数组中所有元素的类型必须相同

应用场景

  • 存储需要按索引快速访问的数据(如查找表)
  • 实现其他数据结构(栈、队列、堆的底层常用数组)
  • 二分查找要求数据存储在数组中(因为需要随机访问)
  • 动态数组(如 Python 的 list、Java 的 ArrayList)在底层也是数组,满了就自动扩容