整个数组所有的元素存储在操作系统分配的一块连续内存中。通过使用元素特定的索引作为数组下标来查找元素。通常可以在常数时间内访问到数组中的某个元素。
1、为什么是常数时间?
为了访问一个数组内的某个元素,由于数组的内存地址在内存中是物理连续的,所以该元素的内存地址 = 基地址 + 元素的大小 * 元素的位置。也就是 ELE_ADD = BASE_ADD + ELE_SIZE * (INDEX - 1)
所以可以总结出数组相关操作的时间复杂度,如下表
参数 | 数组的时间复杂度 |
---|---|
索引 | O(1) |
在最前端插入数据或者删除 | O(n) 需要移动数据 |
在最末端插入数据或者删除 | O(1) |
在中间插入数据或者删除数据 | O(n) |
2、数组的优缺点
- 数组简单易用,只要索引不越界就不会出现意外的bug
- 数据随机访问非常的快
- 数组的容量固定,不能动态的调整
- 数组的空间申请需要连续的空间,有时候可能申请不到连续的内存空间
- 动态插入元素逻辑操作复杂,需要将后面的元素向后移动
3、动态数组
动态数组也成为可边长数组,动态表等等,是一种可随机读取且可以自动调整大小的现行存储结构。实现动态数组的方式,首先初始化一个默认大小的数组空间,一旦数组满了,创建一个两倍于原来空间的数组,将数据拷贝到新的数组中,以此类推。熟悉Java的读者应该发现了,JavaSE 中的 ArrayList 数据结构其 内部原理就类似与动态数组。