我相信在很多地方,大家在进行数据结构的比较的时候,说到数组,第一反应就是—快,但是为什么快呢?数组到底快在哪里呢?不知道大家是否有思考过这个问题,这篇文章,我就讲讲我对数组的一些看法,抛砖引玉,希望大家多多交流!
我们要分析的第一个问题是:
数组到底哪里快?查找快吗?
可能有的同学第一反应利用数组进行查找的话,时间复杂度为O(1)呀。但是你仔细想想,这样说对吗?即使我们对一个已经排好序的数组通过二分查找法进行查找,时间复杂度也为O(logn)。我们更准确的说法是,数组通过角标进行随机访问的时间复杂度为O(1)。那么接下来进入我们要探讨的第二个问题,为什么数组能支持随机访问呢?换而言之,为什么数组能直接通过角标访问元素呢?
为什么数组能支持随机访问呢?
答案:
- 数组占用的内存空间是连续的
- 数组中都为同一类型的元素
举例分析:
我们可以拿一个长度为5的int数组为例,当我们执行了一段int[] arr = new int[5]
后,计算机会给这个数组分配如下图所示的一段内存空间:
当我们访问角标为2的位置上的元素时我们可以直接通过计算得出该元素对于的内存位置:
其中1000是我们的基地址,2代表了我们的偏移量,4代表了每个元素所占内存的大小(int占4个字节)这样通过一次计算,我们就能直接找到数组中对应角标的位置了。讲到这里,我们不妨再思考一个问题,**数组为什么角标都是从0开始呢?**大家想一想,如果我们的角标是从1开始的话,我们上面的公式是不是也得发生变化,就变成了下面这个样子:
这样的话,相对我们之前的公式,是不是平白的多了一次减法的运算?所以,我们角标采用的是相对于基地址的偏移量作为计数标准,这样可以加快我们访问的速度!
通过上面我们知道了,连续的内存空间跟相同的元素这两大利器决定了数组随机访问的特性。另外还需要补充的是,因为数组在内存空间中是连续的,所以CPU在读取时,可以对数组进行“预读”。什么是预读呢?CPU在从内存中加载数据时,会先把读取到的数组加载到CPU的缓存中。而CPU每次从内存中读取数据,并不是只读取那个特定的要访问的地址,而是读取一个数据块,并保存到CPU缓存中,然后下次访问内存数据的时候就会先从CPU缓存开始查找,如果找到就不需要再从内存中取,这样就实现了比直接访问内存更高效的访问机制(这样做的原因是因为,CPU处理数据的速度高于从内存中读取数据的速度)。
关于数组的内容就介绍到这里啦!
喜欢的话,点个赞,加个关注吧!万分感谢
我的数据结构与算法专栏:https://blog.csdn.net/qq_41907991/column/info/42035