第 75 题:数组里面有 10 万个数据,取第一个元素和第 10 万个元素的时间相差多少?
问题
数组里面有10万个数据,取第一个元素和第10万个元素的时间相差多少?
答案
JavaScript 没有真正意义上的数组,所有的数组其实是对象,其 索引 看起来是数字,其实会被转换成字符串,作为属性名(对象的 key)来使用。所以无论是取第 1 个还是取第 10 万个元素,都是用 key 精确查找哈希表的过程,其消耗时间大致相同。
为了更加清楚一点还是使用js来一段代码比较清晰
var arr = new Array(100000).fill(null)
console.time('first')
arr[0]
console.timeEnd('first')
console.time('end')
arr[99999]
console.timeEnd('end')
/*
first: 0.00390625ms
end: 0.0029296875ms
*/
上面测试代码打印结果时间基本可以忽略不计
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
上一篇: 第 76 题:说出以下代码运行结果
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(13)
数组里面有10万个数据,取第一个元素和第10万个元素的时间相差多少?
06-js中的数组
前言
数组、链表、栈、队列都是线性表,它表示的结构都是一段线性的结构,与之对应的就是非线性表,例如树、图、堆等,它表示的结构都非线性。
思考
什么 是数组
以上是js数组在内存中大致位置 ,或者
为什么这么说,因为在
js
中 数组的存储意思是说,我们可以看到
JSArray
是继承自JSObject
的,所以在 JavaScript 中,数组可以是一个特殊的对象,内部也是以 key-value 形式存储数据,所以 JavaScript 中的数组可以存放不同类型的值数组的优点
根据下标随机访问的时间复杂度为 O(1)
数组特性
我们已经知道数组是一段连续储存的内存,当我们要将新元素插入到数组k的位置时呢?这个时候需要将k索引处之后的所有元素往后挪一位,并将k索引的位置插入新元素.
删除操作其实与插入很类似,同样我要删除数组之内的k索引位置的元素,我们就需要将其删除后,为了保持内存的连续性,需要将k之后的元素通通向前移动一位,这个情况的时间复杂度也是O(n).
比如我们要查找一个数组中是否存在一个为2的元素,那么计算机需要如何操作呢?
如果是人的话,在少量数据的情况下我们自然可以一眼找到是否有2的元素,而计算机不是,计算机需要从索引0开始往下匹配,直到匹配到2的元素为止
我们已经强调过数组的特点是拥有相同的数据类型和一块连续的线性内存,那么正是基于以上的特点,数组的读取性能非常的卓越,时间复杂度为O(1),相比于链表、二叉树等数据结构,它的优势非常明显.
那么数组是如何做到这么低的时间复杂度呢?
假设我们的数组内存起始地址为
start
,而元素类型的长度为size
,数组索引为i
,那么我们很容易得到这个数组内存地址的寻址公式:比如我们要读取
arr[3]
的值,那么只需要把3
代入寻址公式,计算机就可以一步查询到对应的元素,因此数组读取的时间复杂度只有O(1).总结
JavaScript 中,
JSArray
继承自JSObject
,或者说它就是一个特殊的对象,内部是以 key-value 形式存储数据,所以 JavaScript 中的数组可以存放不同类型的值。它有两种存储方式,快数组与慢数组,初始化空数组时,使用快数组,快数组使用连续的内存空间,当数组长度达到最大时,JSArray
会进行动态的扩容,以存储更多的元素,相对慢数组,性能要好得多。当数组中hole
太多时,会转变成慢数组,即以哈希表的方式( key-value 的形式)存储数据,以节省内存空间。参考
性能测试
https://jsperf.com/
我竟然去真的去做了实验:
index_0: 0.01708984375ms
index_100000: 0.006103515625ms
index_0: 0.01611328125ms
index_100000: 0.04296875ms
index_0: 0.011962890625ms
index_100000: 0.005859375ms
index_0: 0.012939453125ms
index_100000: 0.0078125ms
index_0: 0.01171875ms
index_100000: 0.0068359375ms
index_0: 0.011962890625ms
index_100000: 0.01904296875ms
index_0: 0.0126953125ms
index_100000: 0.008056640625ms
如果是传统数组的方式,应该是没区别的。
如果是哈希的方式,得看具体的哈希情况,所以是无法预估的,只能说时间复杂度相等。
不过10万条数据的数组在JS里面多半变成哈希了吧。
没多大区别,都是比较短的
用下标是瞬间,链表也瞬间
大佬推荐的这篇文章里,链式哈希查找元素要从第一个去追溯,那index的不同应该是有差距的呀,是我对这篇文章的什么地方理解错了么
js 中数组元素的存储方式并不是连续的,而是哈希映射关系。哈希映射关系,可以通过键名 key,直接计算出值存储的位置,所以查找起来很快。推荐一下这篇文章:深究 JavaScript 数组
正常来说取数组元素应该没差才对,都是按下标取的,也不是像链表那样要逐个查找。
Chrome 浏览器JS引擎 V8中,数组有两种存储模式,一种是类似C语言中的线性结构存储(索引值连续,且都是正整数的情况下),一种是采用Hash结构存储(索引值为负数,数组稀疏,间隔比较大);
结论:以上说明对这个问题都没啥影响,同一个数组,在索引取值的时候,取第一个和最后一个效率没什么差别
JavaScript 没有真正意义上的数组,所有的数组其实是对象,其“索引”看起来是数字,其实会被转换成字符串,作为属性名(对象的 key)来使用。所以无论是取第 1 个还是取第 10 万个元素,都是用 key 精确查找哈希表的过程,其消耗时间大致相同。
@lvtraveler 请帮忙测试下稀松数组。
数组可以直接根据索引取的对应的元素,所以不管取哪个位置的元素的时间复杂度都是 O(1)
得出结论:消耗时间几乎一致,差异可以忽略不计