数组review
数组
数组(Array)是一种线性的数据结构,用一组连续的内存空间,来存储一组具有相同类型的数据。
线性表
数据排列像一条线一样的结构,线性表上的数据最多只有前后两个方向,典型的线性表除了数组,还有链表,队列,栈等。
二叉树,图等都不是线性表。
连续内存空间和相同类型
这种好处是支持随机访问,相同类型表示每个元素的大小是固定的,通过下标就能直接找到元素的内存地址。
定义一个10个数字的int数组a.
int[] a = new int[10];
假定首地址是1000(base_address)。一个int占4位,所以a的内存空间是1000--1039.
每一个数组元素的地址base_address+i * dataTypeSize。本例中dataType位int,所以dataTypeSize位4。
a[i]_address=base_address + i * dataTypeSize
高效的查询
通过上面的存储结构就可以知道,通过下标访问数组只需要O(1)的时间。但是查找本身是需要O(logn)【采用二分查找法】。
低效的插入
数组内存的连续性决定了其插入和删除的低效。因为插入和删除都涉及到数组内存的移动。
末尾插入,效率最高,O(1),其他地方插入需要移动,最坏为O(n),平均复杂度为O(n)。
插入优化:对于无需的数组,插入一个元素,可以将当前的元素移动到末尾,然后在当前元素的位置插入待插入的元素,这样插入的复杂度便变成了O(1)。
上图中插入X,把c移动到了末尾,X插入c的位置,避免了大量元素的移动,复杂度为常数级O(1)。
低效的删除
和插入类似,删除也需要搬移数据,保证内存的连续性。
删除默认元素,效率最高,复杂度为O(1),其他地方删除需要移动,最坏为O(n),平均复杂度为O(n)。
删除优化
多个删除操作可以集中在一起操作,这个就会减少数据搬移的次数,从而提高效率。
具体操作是将需要删除的数据先进行标识,等到一定程度后一次性进行删除和内存搬迁。
上图中a,b,c是分三次删除的,先进行标识,等到一定条件后一次性进行真正的删除,这样d,e,f,g,h只需要搬移一次。