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

时间:2015-06-27 17:59:11

标签: javascript time-complexity ecmascript-6

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

我的期望,我希望大多数开发人员都希望规范和实现使用widely accepted高性能算法,在这种情况下Set.prototype.hasadddelete在一般情况下都是O(1)。 MapWeak–等价物相同。

对我来说,实施的时间复杂性是否是强制性的,这一点并不完全清楚。在ECMAScript 2015 Language Specification - 6th Edition — 23.2 Set Objects

除非我误解它(我当然很可能),看起来ECMA规范要求实现(例如Set.prototype.has)使用线性时间( O(n))算法。令我极为惊讶的是,规范不会强制要求甚至不允许使用更高性能的算法,我会非常感兴趣地解释为什么会出现这种情况。

2 个答案:

答案 0 :(得分:38)

that very paragraph链接到:

  

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

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

  

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

没有

  

Set对象规范中使用的数据结构仅用于描述Set对象所需的可观察语义。它并不是一个可行的实施模型。

可观察的语义主要与可预测的迭代顺序(仍然可以是implemented efficient and fast)相关。规范确实期望实现使用散列表或类似于常量访问的东西,尽管也允许树(具有对数访问复杂性)。

答案 1 :(得分:6)

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

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 w / 16G RAM)

benchmarkMap: 189.120ms
benchmarkHash: 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