Độ phức tạp tính toán / thời gian của Javascript ES6 của các bộ sưu tập


84

Đặc điểm kỹ thuật ES6 cung cấp độ phức tạp về thời gian nào (trong ký hiệu big-O) cho Bộ sưu tập có khóa (Set, Map, WeakSet và WeakMap)?

Kỳ vọng của tôi và tôi mong đợi của hầu hết các nhà phát triển là các thông số kỹ thuật và triển khai sẽ sử dụng các thuật toán hiệu suất được chấp nhận rộng rãi , trong trường hợp đó Set.prototype.has, adddeletetất cả đều là O (1) trong trường hợp trung bình. Tương tự đối với MapWeak–tương đương.

Tôi không hoàn toàn rõ ràng liệu độ phức tạp về thời gian của việc triển khai có được yêu cầu hay không, ví dụ như trong Đặc tả ngôn ngữ ECMAScript 2015 - Phiên bản thứ 6 - 23.2 Đặt đối tượng .

Trừ khi tôi hiểu sai (và chắc chắn là tôi có thể làm vậy), có vẻ như thông số kỹ thuật ECMA yêu cầu việc triển khai (ví dụ Set.prototype.has) phải sử dụng thuật toán thời gian tuyến tính ( O (n) ). Tôi sẽ cực kỳ ngạc nhiên rằng các thuật toán hiệu suất hơn sẽ không được yêu cầu hoặc thậm chí cho phép bởi thông số kỹ thuật và tôi sẽ rất quan tâm đến lời giải thích tại sao lại như vậy.


2
Tất cả các thuật toán O (1) cũng đều là O (n) , vì vậy việc cho phép triển khai ít hiệu suất hơn sẽ không gây hại gì. Có lẽ việc triển khai ít hiệu suất hơn có thể được quan tâm trong các hệ thống có tài nguyên bị hạn chế, vì rất có thể chúng yêu cầu ít mã / không gian hơn nhiều.
artur grzesiak

@arturgrzesiak Hiệu suất O (1) của các tập hợp có khóa thường đạt được với hàm băm O (1) cộng với nhóm va chạm O (n). Trường hợp xấu nhất O (n) dành cho hầu hết các mục đích thực tế rất hiếm về mặt thiên văn. Độ phức tạp không gian của các kỹ thuật này nói chung là O (n).
Brian M. Hunt

1
"Các đối tượng tập hợp phải được triển khai bằng cách sử dụng bảng băm hoặc các cơ chế khác, trung bình, cung cấp thời gian truy cập theo tuyến con về số lượng phần tử trong tập hợp." - từ chính trang đó.
georg

Câu trả lời:


59

Ngay từ đoạn văn đó bạn đã liên kết đến:

Các đối tượng tập hợp phải được triển khai bằng cách sử dụng [cơ chế] mà trung bình, cung cấp thời gian truy cập theo tuyến con về số lượng phần tử trong tập hợp.

Bạn sẽ tìm thấy câu tương tự cho Maps , WeakMapsWeakSets .

Có vẻ như thông số kỹ thuật ECMA yêu cầu việc triển khai (ví dụ: Set.prototype.has) phải sử dụng O(n)thuật toán thời gian tuyến tính ( ).

Không:

Cấu trúc dữ liệu được sử dụng trong Setđặc tả đối tượng này chỉ nhằm mục đích mô tả ngữ nghĩa quan sát được yêu cầu của đối tượng Set. Nó không phải là một mô hình triển khai khả thi.

Các ngữ nghĩa có thể quan sát được chủ yếu liên quan đến thứ tự lặp lại có thể dự đoán được (vẫn có thể được triển khai hiệu quả và nhanh chóng ). Đặc điểm kỹ thuật thực sự mong đợi việc triển khai sử dụng bảng băm hoặc thứ gì đó tương tự với quyền truy cập liên tục, mặc dù cây (với độ phức tạp truy cập logarit) cũng được phép.


2
Cảm ơn vì đã chọn ra. Mắt tôi phải trừng trừng khi tôi đến đoạn đó. :) Vậy các thuật toán là O (log (n)) hoặc O (1), nhưng không bắt buộc theo cách khác (miễn là chúng nằm dưới O (n))?
Brian M. Hunt

1
@ BrianM.Hunt: Đúng.
Bergi

31

Đối với bất kỳ ai tò mò, tôi đã làm một điểm chuẩn rất nhanh:

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);

Tôi đã chạy điều này một vài lần và mang lại kết quả sau:

(MacBook Pro 2017, RAM i7 2,5 GHz w / 16G)

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 nếu bạn tách ra lập từ việc tôi nhận được: Bản đồ Set = 124, Bản đồ Nhận = 40, Object Set = 26, Object Nhận = 1 (đây là tỷ lệ không ms)
AJP

@AJP Tôi đã không nghĩ đến, chia nhỏ nó với những số liệu thống kê đó. Cảm ơn bạn đã đóng góp, đó là một đóng góp tốt. Tôi sẽ xem nếu tôi có thể thêm điều đó vào câu trả lời của mình khi tôi có một giây. Cảm ơn!
domdambrogia

Sẽ rất thú vị nếu tách bài tập ra khỏi bài đọc để tìm hiểu xem bài nào đọc nhanh hơn.
fernandopasik

3
" MacBook Pro 2017, RAM i7 2,5 GHz w / 16G " - uh, thật tuyệt, nhưng bạn đã đánh giá công cụ javascript nào?
Bergi

1
Điều thú vị là, khi các deletehoạt động thêm và các hoạt động được trộn lẫn với nhau, hoạt động Maptốt hơn nhiều. jsfiddle.net/23hrp0eq
Jorjon
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.