一、概念
有限个相同数据类型元素组成的有序集合
在现在的开发语言中,基本都提供了原生的数组数据结构(数组的长度是固定的,中间的元素数据类型是相同的,其索引是从0开始的)
对于数组,我们在进行访问的时候,是通过其下标进行访问的,且访问的时候时间复杂度为O(1),其真实的内存存储的数据是顺序存储;理解:因为一个数组中间的每个元素的数据类型是相同的,则每个元素所占用的内存空间大小是一个固定的,就能够实现知道第一个元素的内存地址就能够知道中间所有元素的内存地址(第一个元素的内存地址+单个元素需要的内存空间大小=下一个元素的内存地址)
二、常见操作
前面介绍到,数组采用的顺序存储的方式,对于在内存中,是处于连续的一块内存区间,对于这样的数据结构,也就有其必然的一些特性
2.1、获取元素
arr[index],时间复杂度为O(1)
前面说到,数组对应的内存空间是一段连续的地址,当要获取数组中某个下标下的元素,我们仅仅需要将下标带入公式(每个元素占用内存空间是一定的,初始地址明确,下标明确),得到对应下标(内存地址)下的元素就非常快
2.2、更新元素
获取一个元素的复杂度是O(1),对应的更新一个元素的复杂度也是O(1)
2.3、插入/删除元素
对于插入和删除元素,如果仅仅是插入或删除数组中的最后一个元素,其复杂度为O(1);但是如果要插入/删除数组中的第一个元素,这样就需要后面所有的元素位置进行挪动,对应的复杂度为O(n)
在上图中,向索引为0的位置插入了一个 50 的元素,可以看到,原来的元素都开始向后移动了一个元素的位置,其复杂度为O(n)
上图中,将索引为0的位置的元素进行删除,后面的元素开始向前面移动一个元素的位置,其复杂度为O(n)
三、小结
通过上面的数组,可以发现其适用的场景应该是查询更新较多的场景,相对而言,并不是很适合插入和删除操作的场合
四、Golang中的数组
五、动态数组
5.1、概述
前面的内容已经讲到了数组(有限个相同数据类型的元素组成的有序集合),可以看到,对于数组,它的数量是有限的,但在日常的开发中,往往需要一个可以随时进行扩容、缩容的数组,此时就出现了动态数组的概念
- 静态数组:编译时就已经确定数组的长度,为了防止空间不足,所以一般情况下我们会将这个数组的长度定义的大一些,但是这样一来容易出现内存浪费的情况
- 动态数组:在编译的时候不需要确定长度,而是在运行的过程中确定
5.2、Golang中的动态数组实现
在Golang中,如果要实现上述所说的动态数组,有专门的数据结构来实现,也就是切片