Tóm tắt Big-O cho việc triển khai Khung sưu tập Java? [đóng cửa]


164

Tôi có thể sẽ sớm dạy "khóa học sự cố Java". Mặc dù có thể an toàn khi cho rằng các thành viên khán giả sẽ biết ký hiệu Big-O, nhưng có lẽ không an toàn khi cho rằng họ sẽ biết thứ tự của các hoạt động khác nhau trên các triển khai bộ sưu tập khác nhau là gì.

Tôi có thể mất thời gian để tự tạo một ma trận tóm tắt, nhưng nếu nó đã có sẵn trong phạm vi công cộng ở đâu đó, tôi chắc chắn muốn sử dụng lại nó (với tín dụng phù hợp, tất nhiên.)

Bất cứ ai có con trỏ?


Đây là một liên kết tôi thấy hữu ích khi thảo luận về một số đối tượng Java rất phổ biến và chi phí hoạt động của chúng bằng cách sử dụng ký hiệu Big-O. objectissues.blogspot.com/2006/11/
Nick

Mặc dù không thuộc phạm vi công cộng, các Bộ sưu tập và bộ sưu tập Java xuất sắc của Maurice Naftalin và Philip Wadler liệt kê các tổng quan thông tin thời gian chạy trong các chương của nó về các lớp bộ sưu tập khác nhau.
Fabian Steeg

1
Điểm chuẩn hiệu suất này sẽ được sử dụng?
ThreaT

Câu trả lời:


149

Trang web này khá tốt nhưng không dành riêng cho Java: http://bigochcoateet.com/ Đây là một hình ảnh trong trường hợp liên kết này không hoạt động


27
Và đây là lý do tại sao chúng tôi không sử dụng URL làm câu trả lời. Tài liệu / máy chủ đó, theo như tôi có thể nói, không còn nữa!
Jason Mock

1
@Ben J Liên kết không còn hoạt động nữa
Vikas V

Các liên kết lưu trữ web bây giờ cũng bị hỏng.
MikeFHay

Có vẻ như các URL làm việc mới được thêm vào. Cảm ơn đã nỗ lực, nó rất hữu ích.
Tejas C

1
@AndreaZilio LinkedList.remove (Object) là thời gian không đổi, giả sử bạn đã biết hàng xóm rồi. Nếu bạn không biết người hàng xóm, đây là lúc tuyến tính tìm thấy nó trước.
Paul Evans

217

Cuốn sách Java Generics and Collection Collection có thông tin này (trang: 188, 211, 222, 240).

Danh sách thực hiện:

                      get  add  contains next remove(0) iterator.remove
ArrayList             O(1) O(1) O(n)     O(1) O(n)      O(n)
LinkedList            O(n) O(1) O(n)     O(1) O(1)      O(1)
CopyOnWrite-ArrayList O(1) O(n) O(n)     O(1) O(n)      O(n)

Đặt triển khai:

                      add      contains next     notes
HashSet               O(1)     O(1)     O(h/n)   h is the table capacity
LinkedHashSet         O(1)     O(1)     O(1) 
CopyOnWriteArraySet   O(n)     O(n)     O(1) 
EnumSet               O(1)     O(1)     O(1) 
TreeSet               O(log n) O(log n) O(log n)
ConcurrentSkipListSet O(log n) O(log n) O(1)

Bản đồ triển khai:

                      get      containsKey next     Notes
HashMap               O(1)     O(1)        O(h/n)   h is the table capacity
LinkedHashMap         O(1)     O(1)        O(1) 
IdentityHashMap       O(1)     O(1)        O(h/n)   h is the table capacity 
EnumMap               O(1)     O(1)        O(1) 
TreeMap               O(log n) O(log n)    O(log n) 
ConcurrentHashMap     O(1)     O(1)        O(h/n)   h is the table capacity 
ConcurrentSkipListMap O(log n) O(log n)    O(1)

Hàng đợi triển khai:

                      offer    peek poll     size
PriorityQueue         O(log n) O(1) O(log n) O(1)
ConcurrentLinkedQueue O(1)     O(1) O(1)     O(n)
ArrayBlockingQueue    O(1)     O(1) O(1)     O(1)
LinkedBlockingQueue   O(1)     O(1) O(1)     O(1)
PriorityBlockingQueue O(log n) O(1) O(log n) O(1)
DelayQueue            O(log n) O(1) O(log n) O(1)
LinkedList            O(1)     O(1) O(1)     O(1)
ArrayDeque            O(1)     O(1) O(1)     O(1)
LinkedBlockingDeque   O(1)     O(1) O(1)     O(1)

Phần dưới cùng của javadoc cho gói java.util chứa một số liên kết tốt:


3
Bạn phải xác định kịch bản trường hợp nào là những số liệu đó, ví dụ, xóa khỏi Arraylist có thể mất O (n), nếu bạn xóa phần tử ở giữa hoặc cuối mảng.
Popeye

@popeye không phải O thường là trường hợp xấu nhất?
Yassin Hajaj

Như @Popeye đã đề cập, cần có một mô tả rõ ràng về trường hợp câu trả lời là về trường hợp nào. Các trường hợp có thể là trung bình / tồi tệ nhất cho sự phức tạp thời gian. Có vẻ như câu trả lời đang đề cập đến một trường hợp "trung bình" cho tất cả DS.
Yashwin Munsadwala

12

Javadocs từ Sun cho mỗi lớp bộ sưu tập thường sẽ cho bạn biết chính xác những gì bạn muốn. HashMap , ví dụ:

Việc triển khai này cung cấp hiệu suất thời gian không đổi cho các hoạt động cơ bản (lấy và đặt), giả sử hàm băm phân tán các phần tử đúng cách giữa các nhóm. Lặp lại các chế độ xem bộ sưu tập yêu cầu thời gian tỷ lệ thuận với "dung lượng" của thể hiện HashMap (số lượng thùng) cộng với kích thước của nó (số ánh xạ giá trị khóa).

Bản đồ cây :

Việc triển khai này cung cấp chi phí thời gian log (n) được bảo đảm cho các thao tác chứaKey, get, put và remove.

Cây :

Việc triển khai này cung cấp chi phí thời gian log (n) được đảm bảo cho các hoạt động cơ bản (thêm, xóa và chứa).

(nhấn mạnh của tôi)


Tôi không đồng ý với phần HashMap. Tôi biết vị trí của Sun, nhưng ... lấy ví dụ phải gọi obj.equals (khóa), có thể là tuyến tính theo kích thước của các đối tượng được chứa. Hãy xem xét rằng bạn thường phải đọc các trường để so sánh này. Các ngoại lệ sẽ là số nguyên hoặc chuỗi (thực tập) ???
Tràn đầy

Trước hết, nếu họ sai, bạn có nên tạo ra một trường hợp thử nghiệm không phù hợp với hiệu suất thời gian không đổi? Thứ hai, nếu bạn xem mã nguồn cho HashMap, nó không gọi bằng () với mỗi khóa trong bản đồ - chỉ khi các mã băm bằng nhau.
matt b

5
Nếu bạn đọc đoạn trích dẫn ở trên, nó nói rằng đó là thời gian không đổi "giả sử hàm băm phân tán các phần tử đúng cách giữa các nhóm". Từ lý thuyết CS, các bảng băm có các hoạt động thời gian không đổi khi hàm băm là "tốt" (trung bình xảy ra), nhưng có thể mất thời gian tuyến tính trong trường hợp xấu nhất.
newacct

4
@Overflown - Về mặt kỹ thuật, không quan trọng obj.equals () mất bao lâu từ góc độ phức tạp, vì đó chỉ là một phần của "hằng số" liên quan đến số lượng vật phẩm trong bộ sưu tập.
mikera

6

Anh chàng ở trên đã đưa ra so sánh cho HashMap / Hashset so với TreeMap / TreeSet.

Tôi sẽ nói về ArrayList so với LinkedList:

Lập danh sách:

  • Ô (1) get()
  • khấu hao O (1) add()
  • nếu bạn chèn hoặc xóa một phần tử ở giữa bằng ListIterator.add()hoặc Iterator.remove(), nó sẽ là O (n) để dịch chuyển tất cả các phần tử sau

Danh sách liên kết:

  • Trên) get()
  • Ô (1) add()
  • nếu bạn chèn hoặc xóa một phần tử ở giữa bằng ListIterator.add()hoặc Iterator.remove(), nó sẽ là O (1)

1
if you insert or delete an element in the middle using ListIterator.add() or Iterator.remove(), it will be O(1) tại sao? đầu tiên chúng ta cần tìm phần tử ở giữa, vậy tại sao nó không phải là O (n)?
MyTitle

@MyTitle: đọc lại. "Sử dụng ListIterator.add()hoặc Iterator.remove()" Chúng tôi có một trình vòng lặp.
newacct
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.