简单了解数组 - 图

124 阅读2分钟

数组的定义

  • 线性
  • 内存连续

数组是一个线性的以及内存连续的数据结构. 就是数组有前后顺序, 而且是一个挨着一个. 就跟买奶茶排队一样, 挨个排好.

未命名.gif

线性结构

Untitled.png

具有线性的结构:

  • 数组
  • 队列
  • 链表

可以就是有前后顺序, 先来后到, 从前一个可以找到后一个.

非线性结构

Untitled 1.png

  • 树形

非线性结构就是没有前后之分, 是比较复杂的结构.

内存连续

内存连续就是指, 存放的地方都是挨着的.

比方说:

const arr: number[] = [1, 2, 3, 4, 5]

在内存中表示:

Untitled 2.png 给内存分配1000-1021的区域, 用来存放数组arr. 他们需要连续挨着.

那么我们怎么去访问数组中的数据的呢?

随机访问

就是以下公式去访问

a[i]_address = base_address + i * data_type_size

base_address: 就是指内存的开始. 例子中指的是: 1000

data_type_size: 指的是存储数据需要用多少内存.

i: 是数组中的第几个.

这样就能访问到内存地址中存储的数据了.

可以看到数组支持随机访问, 用下标去随机访问的时间复杂度为 O(1)

数组的劣势

数组为了保持内存数据的连续性,会导致插入、删除这两个操作比较低效。

插入

还是以排队来举例, 当我们排队的时候, 有个人要插队, 会让排在后面的人非常不爽.

未命名 1.gif

可以看到当插入之后, 后面的每个人都需要往后移动一个位置. 这可是一个大动作了.

删除

删除相当于就是中间有个人排着排着, 不排了, 人走了. 后面的所有人都得向前移动一步, 也是个大动作了.

未命名 2.gif

删除优化

当然了, 如果每次删除都移动数组的话, 内存开销会比较大, 影响性能, 咱们可以将多次删除合并, 一起操作, 减少移动.

未命名 3.gif

数组为何从0开始?

对比一下从0开始, 和从1开始公式的不同

从0开始:

a[k]_address = base_address + k * type_size

从1开始:

a[k]_address = base_address + (k-1)*type_size

从1开始会多一次-1的cpu指令, 性能会差一点.