集合、列表和数组
先简单介绍一下集合、列表和数组
这三者的区别。
数组是列表的实现方式之一
如何区分列表和数组呢
数组有索引,索引从0算起,我们可以根据数组中的索引访问数组中的元素,而列表没有索引。
数组的元素在内存中是连续存储的,且每个元素占用相同大小的内存,而列表中的元素可能彼此相邻也可能不相邻,比如另一个实现方式链表就不一定是连续的。
数组的操作
- 读取元素
读取数组中的元素,是通过访问索引的方式来读取的。
计算机中的内存可以看作是一个个整齐排列的小格子,每个格子对应一个内存地址,一般情况下数据会分散在不同的格子中。
而对于数组,计算机会在内存中专门划分出一段连续的空间,并记下索引为0
处的内存地址。
以数组{“A”,“B”,“C”,“D”}为例,它的各元素对应的索引及内存地址如下
数组 | “A” | “B” | “C” | “D” |
---|---|---|---|---|
索引 | 0 | 1 | 2 | 3 |
内存地址 | 2004 | 2005 | 2006 | 2007 |
当我们访问索引为2
处的元素"D"
时,计算机会进行以下计算
-
找到该数组的索引
0
的内存地址2004
-
将内存地址加上索引值,作为目标元素的地址,即
2004+2=2006
,对应的元素为"C"
,此时便找到了目标元素。
这个过程的时间复杂度时常数级别,为O(1)。
- 查找元素
当我们不清楚数组的元素,想确定其中是否含有元素B
时,计算机会如何操作呢
由于只保留了索引为0
处的内存地址,因此在查找元素时,计算机会先找到0
处的内存地址,然后再逐一向后查找。
查找元素的时间复杂度为O(N),N为数组的长度。
- 插入元素
如果将元素插入的是数组的末尾,则计算机通过计算数组长度和位置计算出即将插入元素的内存地址,然后插入到指定位置即可。
但是要将元素插入到数组中的其他位置,就要先给这个元素腾位置,这个元素后面的元素都要向后挪,再将这个元素插进去。
就像打麻将要插入某张牌一样,要将其后的牌都先挪出空位再将牌插进去。
- 删除元素
与插入元素类似,删除某个元素后,数组会留下空缺的位置,这时后面的元素就需对该位置进行填补。
当数组的长度为n
时,删除第一个元素所需的步骤数为1+(n-1)=n
步,删除操作具有线性时间复杂度,即时间复杂度为 O(N),N 为数组的长度。