一.数组Array
数组的存储在计算机内存中是一片连续的区域。而且数组中每一项所占内存的大小是一定的。因此,我们只需要知道数组第一项所处的位置,就能简单的知道其他任何项所在的位置,而不需要依次去查找。所以数组在知道索引时的访问是很快的。
二.未排序数组的插入
对于未排序的数组,当我们要插入一个新的值时,我们要改变数组的长度,即在数组末尾加一个新的项,然后将值存入。所以它的耗时 T 是和数组现在的长度 N 无关的,我们可以认为这个耗时是一个常量 K。即:
T = K;
这里的常量的值是取决于机器运算的快慢等。因此其时间复杂度为O(1)。
三.线性搜索
线性搜索意思是从数组第一个项一直查到最后一个项。并找出我们需要的值。
在最理想的情况下,我们需要的项在第一个,所以耗时为K(运算常量),最坏的情况是在最后一个,耗时为K*N.所以平均下来,线性搜索耗时:
T = K * N / 2
即:线性搜索的耗时和数组长度成正比。因此其时间复杂度为O(n)。
四.二分搜索
二分搜索的条件是数组是有序的,我们看电视里CCTV2购物街中经常有猜商品价格的节目。这里假如是这样:猜在0-100中的一个数,当你选择一个数时,如果是想要的数,搜索结束,如果不是,我们告诉你这个数是偏大或偏小。
时间和长度的关系如下:
T = K * log2(N).
可以看出,这个对效率的提升可不是一点点了。当然,不要忘记,只能在有序列表中才能用二分查找。因此其时间复杂度为O(logn).
五.比较
六.为何不总是使用数组?
数组的一些参数已经在上表中列出,我们为何不在所有的场合都使用数组呢?
上面我们已经看到数组的优劣。在未排序数组中,插入一个新的值只需要O(1),但要找到一个值就要遍历整个数组,即需要O(N)的时间。在有序数组中,查找很快,只要O(logN),但插入的时候要判断值的大小,所以要找到比插入值大和小的值所在的位置,即要O(N)的时间。对两种数组,删除一个值都要O(N)的时间,因为删除一个值后,它后面的所有值都要往前移,以填补删除带来的空白。
数组还有一个问题就是,它的长度是固定的。当我们声明一个数组类型的对象时,它的长度就确定了。即计算机分配给这个对象的内存区域就已经确定了,我们只能在这个区域进行数据的存储。如果我们尽量声明大点的数组,可能存储空间的浪费。如果太小,数据可能不够放。所以在JAVA中,出现了两个新的数据容器:ArrayList 和 LinkedList, 它们都允许动态的改变数组的大小。实际上它是再重新声明一个数组,然后将原数组的内容复制到新的里面。
在JAVA中还有一个容器叫Vector,它和数组非常的象,但它是可扩展的。当然这是以牺特征一些效率换来的。就象上面说的ArrayList和LinkedList一样,有些功能的效率是不如数组的。
七.总结
1. 数组在JAVA中是一个对象,用new关键字来声明。
2. 未排序数组的插入更快,但查找要慢。
3. JAVA中的数组是包装在Array.class中的,这样就防止了随意更改。
4. 二分法在有序列表中的查找是非常快的。