2017-01-30 17 views
5

Thời gian dài trước đây, tôi đã xem một bài giảng video từ Princeton Coursera MOOC: Giới thiệu về các thuật toán, có thể được tìm thấy here. Nó giải thích chi phí thay đổi kích thước cấu trúc giống như ArrayList trong khi thêm hoặc xóa các phần tử khỏi cấu trúc đó. Nó chỉ ra rằng nếu chúng tôi muốn cung cấp thay đổi kích thước cho cấu trúc dữ liệu của chúng tôi, chúng tôi sẽ đi từ O(n) đến amortized O(n) cho các hoạt động addremove.Tại sao Java ArrayLists không co tự động

Tôi đã sử dụng Java ArrayList trong một vài năm. Tôi đã luôn luôn chắc chắn rằng họ phát triển và thu nhỏ tự động. Chỉ gần đây, với sự ngạc nhiên lớn của tôi, tôi đã được chứng minh là sai trong this post. Java ArrayList s không co lại (mặc dù, tất nhiên chúng phát triển) một cách tự động.

Dưới đây là những câu hỏi của tôi:

  1. Theo tôi cung cấp bị thu hẹp trong ArrayList s không thực hiện bất kỳ tác hại như việc thực hiện đã là amortized O(n). Tại sao những người tạo Java không đưa tính năng này vào thiết kế?

  2. Tôi biết rằng các cấu trúc dữ liệu khác như HashMap cũng không tự động thu nhỏ. Có cấu trúc dữ liệu nào khác trong Java được xây dựng trên các mảng hỗ trợ thu hẹp tự động không?

  3. Xu hướng bằng các ngôn ngữ khác là gì? Làm thế nào để tự động thu hẹp trông giống như trong trường hợp danh sách, từ điển, bản đồ, bộ trong Python/C# vv. Nếu chúng đi theo hướng ngược lại với Java, thì câu hỏi của tôi là: tại sao?

+4

Nhược điểm của việc thu hẹp thùng chứa là bạn sẽ phải phát triển lại nếu bạn thêm nhiều yếu tố. Chỉ vì bạn đã xóa các phần tử khỏi danh sách của mình nên thư viện không thể giả sử bạn vẫn không cần dung lượng. Tôi không biết về một trình bao bọc mảng như 'ArrayList' tự động co lại, và tôi sẽ rất ngạc nhiên khi thấy một cái làm điều đó.Nếu bạn là một người dùng 'ArrayList' biết rằng khả năng danh sách của bạn bây giờ có thể bị giảm, bạn có thể sử dụng [' trimToSize() '] (https://docs.oracle.com/javase/7/docs/api/java/util /ArrayList.html#trimToSize()). – khelwood

+0

Tôi hiểu rằng có nhiều việc phải làm, nhưng trong điều kiện 'O', bạn sẽ mất" không có gì "nếu bạn cung cấp thu hẹp tự động, như được trình bày trong video. Sự phức tạp của 'add' và' remove' vẫn là 'amortized O (n)' – GA1

+0

btw, tôi rất thích đọc một phản hồi mang tính xây dựng nếu ai đó đưa ra '-1'. – GA1

Trả lời

2

Nhận xét đã bao gồm hầu hết những gì bạn đang yêu cầu. Dưới đây một số suy nghĩ về câu hỏi của bạn:

  1. Khi tạo một cấu trúc giống như ArrayList trong Java, các nhà phát triển đưa ra quyết định nào đó liên quan đến thời gian chạy/hiệu suất. Họ rõ ràng đã quyết định loại trừ thu hẹp từ các hoạt động "bình thường" để tránh thời gian chạy bổ sung, cần thiết.

  2. Câu hỏi đặt ra là lý do bạn muốn thu nhỏ tự động. Các ArrayList không phát triển nhiều (yếu tố là khoảng 1,5; newCapacity = oldCapacity + (oldCapacity >> 1), để được chính xác). Có lẽ bạn cũng chèn ở giữa và không chỉ phụ thêm vào cuối. Sau đó, LinkedList (không dựa trên một mảng -> không cần thu hẹp) có thể tốt hơn. Nó thực sự phụ thuộc vào trường hợp sử dụng của bạn. Nếu bạn nghĩ rằng bạn thực sự cần tất cả mọi thứ một ArrayList hiện, nhưng nó phải co lại khi loại bỏ các yếu tố (tôi nghi ngờ bạn thực sự cần điều này), chỉ cần mở rộng ArrayList và ghi đè lên các phương pháp. Nhưng hãy cẩn thận! Nếu bạn co lại ở mọi lần xóa, bạn sẽ quay lại tại O(n).

  3. C# List và C++ vector hành xử giống nhau liên quan đến việc thu hẹp danh sách khi xóa các phần tử. Nhưng các yếu tố tự phát triển khác nhau. Ngay cả một số triển khai Java cũng sử dụng các yếu tố khác nhau.

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