2011-09-05 32 views
11

Làm thế nào các mảng ruby ​​được thực thi nội bộ (chủ yếu trong CRuby, nhưng bất kỳ thông tin nào khác được hoan nghênh)?ruby ​​array internals

Chúng có thể phát triển các mảng như vectơ C++ hay chúng dựa trên danh sách? Sự phức tạp của sự dịch chuyển/unshift và truy cập một phần tử theo chỉ mục là gì?

+3

Chỉ cần kiểm tra depo SVN và đọc mã nguồn. Việc thực hiện không thực sự khó cho một lập trình viên C. – texasbruce

Trả lời

15

Chúng là mảng có thể phát triển "tăng trưởng ở cuối".

shiftO(1), unshiftO(n) và truy cập theo chỉ mục là O(1). Theo hiểu biết tốt nhất của tôi, điều này đúng với tất cả các triển khai ruby, nhưng nó chắc chắn có trong MRI.

+2

Tôi không chắc chắn ca luôn là O (N). Nếu tôi nhớ chính xác, sự khởi đầu của khối bộ nhớ và chỉ mục của mục đầu tiên được theo dõi riêng biệt, vì vậy bạn có thể thực hiện thay đổi O (1) bằng cách tăng chỉ mục firstItem. Unshift chỉ là O (N) nếu bạn không thực hiện bất kỳ thay đổi nào. – AShelly

+0

@AShelly: Bạn có vẻ đúng về 'shift' (mặc dù nó không thực sự theo dõi chỉ mục bắt đầu, nhưng thay vào đó làm cho mảng được chia sẻ), nhưng' unshift' chắc chắn là 'O (n)' - nó gọi ' memmove' trên mảng không có vấn đề gì. – sepp2k

+0

Có người nên làm một số tiêu chuẩn để xem. –

2

unshift là O (N^2) trong ruby1.9 của tôi.

$ /usr/bin/time ruby -e 'n=100000;l=[];(1..n).each{|i| l.push(i);}' 
     0.03 real   0.02 user   0.00 sys 
$ /usr/bin/time ruby -e 'n=100000;l=[];(1..n).each{|i| l.unshift(i);}' 
     3.15 real   3.11 user   0.01 sys 
$ /usr/bin/time ruby -e 'n=200000;l=[];(1..n).each{|i| l.unshift(i);}' 
     12.96 real  12.85 user   0.03 sys 
$ ruby -v 
ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-darwin11.3.0] 
+0

Đúng nếu tôi sai nhưng điều này cho thấy rằng unshift có độ phức tạp bậc hai không? Nếu unshift là tuyến tính, khi bạn tăng n từ 100.000 lên 200.000, bạn sẽ không mong đợi thời gian tăng gấp đôi. Khi n được tăng lên bằng hệ số 2, thời gian thực hiện để hoàn thành thuật toán được tăng lên bằng hệ số 4. Số lượng hoạt động tỷ lệ thuận với kích thước của tập dữ liệu bình phương. – louism2

+1

@ louism2 phải ... Tôi cố định vào O (N^2), và nhận thấy rằng unshift() là O (N) trong Ruby2, và O (N^2) trong Ruby1.9. –

+0

Nếu unshift là O (n) và bạn gọi nó là n lần nó sẽ mất thời gian O (n^2) .. tôi cũng tưởng tượng bạn muốn có nhiều hơn hai điểm dữ liệu cho một xu hướng .. – olleicua

Các vấn đề liên quan