Ngày xưa, trong lớp cấu trúc dữ liệu, chúng ta đã học được cách cây AVL hoạt động . Tôi đã có được điều đó trong một trong các lớp học của mình, nhưng người hướng dẫn nói rằng "bạn sẽ không bao giờ thực sự sử dụng thứ này" và thay vào đó chúng tôi đã học 2-3 cây và b * cây thay thế. Đó là những ngày mà bộ nhớ bị hạn chế và các quy trình được xâu chuỗi đơn lẻ. Bạn đã không sử dụng một deque khi một danh sách liên kết đơn cũng sẽ hoạt động tốt.
Danh sách bỏ qua ngày nay phổ biến hơn nhiều với bộ nhớ khả dụng hơn và đồng thời là một vấn đề (bạn không cần phải khóa nhiều khi đóng vai trò là nhà văn trong danh sách bỏ qua - so với mọi thứ với cây AVL).
Thành thật mà nói, đó là cấu trúc dữ liệu yêu thích của tôi bây giờ ở chỗ nó là thứ tôi có thể dễ dàng suy luận về cách thức hoạt động của nó bên dưới và nơi mà nó sẽ có lợi thế hoặc bất lợi khi sử dụng.
Bạn sẽ không cần phải viết một từ đầu (trừ khi bạn nhận được nó như một câu hỏi phỏng vấn - nhưng sau đó bạn có khả năng thực hiện một cây AVL).
Bạn đang đi đến cần phải hiểu lý do tại sao bạn muốn chọn một ConcurrentSkipListMap
trong Java chứ không phải là một HashMap
hoặc TreeMap
hoặc bất kỳ việc triển khai bản đồ khác.
Để hiểu cách thức hoạt động của nó, bạn cần hiểu cách cây nhị phân hoạt động. Chờ đã, để tôi sửa đổi điều đó. Bạn cần hiểu làm thế nào một cây nhị phân cân bằng hoạt động. Không cân bằng cây nhị phân, bạn không nhận được bất kỳ lợi thế thực sự nào với việc tra cứu nó.
Hãy nói rằng chúng ta đã có cây này:
Và chúng tôi chèn một '8' vào nó. Bây giờ chúng tôi đã có:
Và điều đó không cân bằng. Vì vậy, chúng tôi đi và làm điều kỳ diệu là cân bằng nó thông qua một số thực hiện ...
Và bạn đã có một cây cân bằng một lần nữa. Nhưng đó là rất nhiều phép thuật tôi vẫy tay.
Hãy có một danh sách bỏ qua.
Điều này xảy ra là một lý tưởng hóa. Rất ít, nhưng nó cho thấy bản chất cây nhị phân cân bằng mà lý tưởng skiplist xấp xỉ.
Bây giờ, chúng tôi muốn chèn 6 vào đó. Đây là chèn nó giống như một danh sách liên kết. Tuy nhiên, chúng tôi bắt đầu từ đầu và đi xuống. Các điểm trên đến 5. Là 6> 5? Đúng. Ok, điểm cao nhất đến cuối cùng bây giờ, vì vậy chúng tôi đi xuống ngăn xếp (chúng tôi ở trên 5). Tiếp theo là 7. Là 6> 7? Không. Vì vậy, chúng tôi đi xuống một cấp độ và chúng tôi ở cấp độ cơ sở vì vậy chúng tôi chèn 6 ở bên phải của 5.
Chúng tôi lật một đồng xu - đầu chúng tôi xây dựng, đuôi chúng tôi ở lại. Đuôi. Không cần phải làm gì thêm.
Bây giờ hãy chèn 8 cái đó. 8> 5? Vâng. 8> 7? Vâng. Và bây giờ chúng tôi lại ở cấp độ dưới cùng một lần nữa sau khi đi theo mũi tên và ngăn xếp xung quanh và chúng tôi kiểm tra 8> 11? Không. Vì vậy, chúng tôi chèn 8 ở bên phải của 7.
Chúng tôi lật một đồng xu - đầu chúng tôi xây dựng, đuôi chúng tôi ở lại. Đuôi. Không cần phải làm gì thêm.
Trong cây cân bằng, chúng ta sẽ làm việc với nhau về việc cây không được cân bằng ngay bây giờ. Nhưng đây không phải là một cái cây - đó là một danh sách bỏ qua. Chúng tôi ước chừng một cây cân bằng.
Bây giờ, hãy chèn 10. Tôi sẽ tránh tất cả các so sánh.
Chúng tôi lật một đồng xu - đầu chúng tôi xây dựng, đuôi chúng tôi ở lại. Thủ trưởng! Và lật nó lần nữa, Thủ trưởng một lần nữa! Lật nó một lần nữa, ok, có một cái đuôi. Hai cấp trên danh sách liên kết cơ sở.
Ưu điểm ở đây là bây giờ nếu chúng ta sẽ chèn 12, chúng ta có thể bỏ qua từ 5 đến 10 mà không cần thực hiện tất cả các so sánh khác. Chúng ta có thể bỏ qua chúng với danh sách bỏ qua. Và chúng ta không phải lo lắng về cây cân bằng - tính chất xác suất của việc xếp chồng làm điều đó cho chúng ta.
Tại sao điều này rất hữu ích? Bởi vì khi chèn 10 tôi có thể làm điều đó bằng cách khóa ghi trên con trỏ 5 và 7 và 8 chứ không phải toàn bộ cấu trúc. Và trong khi tôi đang làm điều đó, độc giả vẫn có thể xem qua danh sách bỏ qua mà không có trạng thái không nhất quán. Để sử dụng đồng thời, nó nhanh hơn không phải khóa. Để lặp lại lớp dưới cùng, nó nhanh hơn một cái cây (niềm vui của thuật toán BFS và DFS cho điều hướng cây - bạn không phải lo lắng về chúng).
Bạn sẽ gặp nó chứ? Bạn có thể sẽ thấy nó được sử dụng ở những nơi. Và sau đó bạn sẽ biết lý do tại sao tác giả chọn triển khai đó thay vì một TreeMap
hoặc HashMap
cho cấu trúc.
Phần lớn trong số này đã được mượn từ bài đăng trên blog của tôi: Danh sách bỏ qua