Javascript ES6集合的计算/时间复杂度


84

ES6规范为键集合(Set,Map,WeakSet和WeakMap)提供了什么时间复杂度(大O表示)?

我的期望,我期望的大多数开发人员,是规范和实现将使用被广泛接受的高性能算法,在这种情况下Set.prototype.hasadddelete在平均情况下都是O(1)。这同样适用于MapWeak–等效物。

对我来说,实现的时间复杂性是否在例如ECMAScript 2015 Language Specification-6th Edition — 23.2 Set Objects中规定,并不是完全显而易见的。

除非我误解了(当然我确实很可能这样做),否则ECMA规范要求实现(例如Set.prototype.has)必须使用线性时间(O(n))算法。令我惊讶的是,规范中没有要求或什至不允许使用性能更高的算法,并且我对解释为何如此的情况非常感兴趣。


2
所有O(1)算法也都是O(n),因此让性能较低的规范实现不会造成任何危害。性能较差的实现可能在资源受限的系统中可能会引起一些关注,因为它们最有可能需要更少的代码/空间。
artur grzesiak

@keyurgrzesiak密钥集合的O(1)性能通常是通过O(1)哈希加上O(n)碰撞桶来实现的。O(n)最坏的情况从实际意义上讲在天文上是罕见的。这些技术的空间复杂度通常为O(n)。
Brian M. Hunt 2015年

1
“必须使用哈希表或其他机制来实现Set对象,平均而言,它们提供的访问时间与集合中元素的数量成线性关系。”-从该页面开始。
乔治,2015年

Answers:


59

该段开始,您就链接到:

集合对象必须使用[机制]实现,这些机制平均提供的访问时间与集合中元素的数量成线性关系。

您将为MapsWeakMapsWeakSets找到相同的句子。

看起来ECMA规范要求实施(例如Set.prototype.has)必须使用线性时间(O(n))算法。

没有:

Set对象规范中使用的数据结构仅用于描述Set对象所需的可观察的语义。它并非旨在成为可行的实施模型。

可观察的语义主要与可预测的迭代顺序有关(仍然可以高效且快速实现)。规范确实希望实现可以使用哈希表或类似的常量访问方式,尽管也允许使用树(具有对数访问复杂性)。


2
感谢您挑选。当我到达那一段时,我的眼睛一定已经呆呆了。:)那么,算法是O(log(n))还是O(1),但没有其他要求(只要它们在O(n)下)?
Brian M. Hunt 2015年

1
@ BrianM.Hunt:正确。
Bergi 2015年

31

对于任何好奇的人,我做了一个非常快速的基准测试:

const benchmarkMap = size => {
  console.time('benchmarkMap');
  var map = new Map();
  for (var i = 0; i < size; i++) map.set(i, i);
  for (var i = 0; i < size; i++) var x = map.get(i);
  console.timeEnd('benchmarkMap');
}

const benchmarkObj = size => {
  console.time('benchmarkObj');
  var obj = {};
  for (var i = 0; i < size; i++) obj[i] = i;
  for (var i = 0; i < size; i++) var x = obj[i];
  console.timeEnd('benchmarkObj');
}

var size = 1000000;

benchmarkMap(size);
benchmarkObj(size);

我运行了几次,结果如下:

(2017 MacBook Pro,2.5 GHz i7带16G RAM)

benchmarkMap: 189.120ms
benchmarkObj: 44.214ms

benchmarkMap: 200.817ms
benchmarkObj: 38.963ms

benchmarkMap: 187.968ms
benchmarkObj: 41.633ms

benchmarkMap: 186.533ms
benchmarkObj: 35.850ms

benchmarkMap: 187.339ms
benchmarkObj: 44.515ms

3
@domdambrogia(如果您将设置与获取信息分开):映射集= 124,映射获取= 40,对象集= 26,对象获取= 1(这些比率不是ms)
AJP

@AJP我没想到,也将这些统计数据分解了。感谢您的输入,这是一个很好的贡献。我待会儿再看看是否可以将其添加到答案中。谢谢!
domdambrogia

将作业与阅读分开,同时了解两者中哪一个阅读速度更快,这将很有趣。
fernandopasik

3
2017 MacBook Pro,带有16G RAM的2.5 GHz i7和2.5 GHz i7 ”-嗯,这很酷,但是您基准测试了哪个javascript引擎
Bergi

1
有趣的是,当添加delete操作和操作混合在一起时,Map性能要好得多。jsfiddle.net/23hrp0eq
Jorjon
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.