Javascript ES6 обчислювальна / часова складність колекцій


85

Яку складність часу (у великих позначеннях O) забезпечує специфікація ES6 для колекцій клавіш (Set, Map, WeakSet та WeakMap)?

Мої очікування, і я очікую , що від більшості розробників, є те , що специфікації і реалізації будуть використовувати широко прийняті продуктивним алгоритми, в цьому випадку Set.prototype.has, addі deleteдля всіх бути O (1) в середньому випадку. Те саме для Mapі Weak–еквівалентів.

Для мене не зовсім очевидно, чи була тимчасова складність реалізацій встановлена, наприклад, у специфікації мови ECMAScript 2015 - 6-е видання - 23.2 Набір об’єктів .

Якщо я не неправильно розумію це (і це, звичайно, дуже можливо), схоже, специфікація ECMA вимагає, щоб реалізації (наприклад Set.prototype.has) використовували алгоритм лінійного часу ( O (n) ). Мені здається надзвичайно дивовижним, що специфікація не передбачає або навіть дозволить більш ефективні алгоритми, і мені було б дуже цікаво пояснити, чому це так.


2
Всі алгоритми O (1) також є O (n) , тому введення специфікованих менш ефективних реалізацій не завдає шкоди. Можливо, менш ефективні реалізації можуть представляти певний інтерес для систем з обмеженими ресурсами, оскільки, швидше за все, вони вимагають набагато менше коду / простору.
artur grzesiak

@arturgrzesiak Ефективність O (1) наборів ключів, як правило, досягається за допомогою хешу O (1) плюс відро зіткнення O (n). Найгірший випадок O (n) є для більшості практичних цілей астрономічно рідкісним. Космічна складність цих методів, як правило, O (n).
Брайан М. Хант,

1
"Об'єкти набору повинні бути реалізовані за допомогою хеш-таблиць або інших механізмів, які в середньому забезпечують час доступу, який є підлінійним за кількістю елементів у колекції." - саме з цієї сторінки.
georg

Відповіді:


60

Прямо з того самого абзацу, до якого ви посилаєтесь:

Об'єкти набору повинні бути реалізовані за допомогою [механізмів], які в середньому забезпечують час доступу, який є підлінійним за кількістю елементів у колекції.

Ви знайдете те саме речення для Maps , WeakMaps і WeakSets .

Схоже, специфікація ECMA вимагає, щоб реалізації (наприклад, Set.prototype.has) використовували O(n)алгоритм лінійного часу ( ).

Немає:

Структури даних, що використовуються в цій Setспецифікації об’єктів, призначені лише для опису необхідної спостережуваної семантики об’єктів Set. Він не призначений для життєздатної моделі реалізації.

Спостережувана семантика здебільшого пов’язана з передбачуваним порядком ітерацій (який досі може бути реалізований ефективно та швидко ). Специфікація справді передбачає, що реалізація використовує хеш-таблицю або щось подібне з постійним доступом, хоча дерева (зі складністю логарифмічного доступу) також дозволені.


2
Дякую, що вибрали це. На той час, коли я дійшов до цього абзацу, мої очі, напевно, скляніли. :) Отже, алгоритми, які є або O (log (n)), або O (1), але не передбачені іншим чином (за умови, що вони знаходяться під O (n))?
Брайан М. Хант,

1
@ BrianM.Hunt: Правильно.
Бергі,

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 ГГц i7 з 16 ГБ оперативної пам'яті)

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, якщо відокремити налаштування від отримання I get: Map Set = 124, Map Get = 40, Object Set = 26, Object Get = 1 (це співвідношення не мс)
AJP

@AJP Я не думав про це, розбиваючи це за допомогою цієї статистики. Дякуємо за ваш внесок, це хороший внесок. Я побачу, чи зможу я це додати у свою відповідь, коли у мене буде секунда. Дякую!
домдамброгія

Було б цікаво відокремити завдання від читання, щоб також дізнатись, яке з них швидше для читання.
fernandopasik

3
" 2017 MacBook Pro, 2,5 ГГц i7 з 16 ГБ оперативної пам'яті " - це круто, і все, але який движок javascript ви встановили?
Бергі

1
Цікаво, що при додаванні deleteоперації та операції, змішані між собою, Mapвиконують набагато краще. jsfiddle.net/23hrp0eq
Джорджон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.