Bạn đang thiếu cách hai cấu trúc dữ liệu xử lý các va chạm băm. Các bộ lọc nở không lưu trữ các giá trị thực tế, vì vậy không gian cần thiết là kích thước không đổi của mảng được chỉ định. Thay vào đó nếu bạn sử dụng hàm băm truyền thống, nó sẽ cố gắng lưu trữ tất cả các giá trị bạn cung cấp cho nó, để nó phát triển theo thời gian.
Hãy xem xét một hàm băm đơn giản hóa (chỉ vì một ví dụ!) f(x) = x % 2
. Bây giờ bạn nhập các số nguyên sau : 2, 3, 4, 5, 6, 7
.
Hash chuẩn: các giá trị đã cho sẽ được băm và chúng tôi kết thúc với rất nhiều va chạm do f(2) = f(4) = f(6) = 0
và f(3) = f(5) = f(7) = 1
. Tuy nhiên, hàm băm lưu trữ tất cả các giá trị này và nó sẽ có thể cho bạn biết rằng 8
nó không được lưu trữ trong đó. sao làm được vậy? Nó theo dõi các va chạm và lưu trữ tất cả các giá trị có cùng giá trị băm, sau đó khi bạn truy vấn nó, nó sẽ so sánh truy vấn của bạn. Vì vậy, hãy truy vấn bản đồ cho 8
: f(8) = 0
, vì vậy nó sẽ xem xét một nhóm mà chúng tôi đã chèn 2, 4, 6
và cần thực hiện 3 so sánh để cho bạn biết rằng đó 8
không phải là một phần của đầu vào.
Bộ lọc Bloom: Thông thường, mỗi giá trị đầu vào được băm đối với k
các hàm băm khác nhau. Một lần nữa, để đơn giản, hãy giả sử rằng chúng ta chỉ sử dụng hàm băm duy nhất f
. Chúng ta cần một mảng gồm 2 giá trị sau đó và khi chúng ta gặp đầu vào, 2
điều đó có nghĩa là do f(2) = 0
chúng ta đặt giá trị mảng ở vị trí 0
thành giá trị 1
. Điều tương tự xảy ra cho 4
và 6
. Tương tự, 3, 5, 7
mỗi đầu vào đặt vị trí mảng 1
thành giá trị 1
. Bây giờ chúng tôi truy vấn nếu 8
là một phần của đầu vào: f(8) = 0
và mảng ở vị trí 0
là 1
, vì vậy bộ lọc nở sẽ tuyên bố sai đó 8
thực sự là một phần của đầu vào.
Để thực tế hơn một chút, hãy xem xét rằng chúng ta thêm hàm băm thứ hai g(x) = x % 10
. Cùng với đó, giá trị đầu vào 2
dẫn đến hai giá trị băm f(2) = 0
và g(2) = 2
và hai vị trí mảng tương ứng sẽ được thiết lập để 1
. Tất nhiên, mảng bây giờ nên có kích thước tối thiểu 10
. Nhưng khi chúng tôi truy vấn, 8
chúng tôi sẽ kiểm tra mảng tại vị trí 8
do g(8) = 8
và vị trí đó sẽ vẫn còn 0
. Đó là lý do tại sao các hàm băm bổ sung làm giảm các giá trị dương bạn sẽ nhận được.
So sánh: Bộ lọc nở sử dụng k
các hàm băm có nghĩa là lên đến k
các vị trí mảng ngẫu nhiên đang được truy cập. Nhưng con số đó là chính xác. Thay vào đó, hàm băm chỉ đảm bảo cho bạn thời gian truy cập liên tục được khấu hao, nhưng có thể hủy tạo tùy thuộc vào bản chất của hàm băm và dữ liệu đầu vào của bạn. Vì vậy, nó thường nhanh hơn, ngoại trừ các trường hợp khử.
Tuy nhiên, một khi bạn có xung đột băm, hàm băm tiêu chuẩn sẽ phải kiểm tra sự bằng nhau của các giá trị được lưu trữ so với giá trị truy vấn. Việc kiểm tra tính bằng này có thể tốn kém tùy ý và sẽ không bao giờ xảy ra với bộ lọc nở.
Về không gian, bộ lọc nở là không đổi, vì không bao giờ có nhu cầu sử dụng nhiều bộ nhớ hơn mảng được chỉ định. Mặt khác, hàm băm phát triển linh hoạt và có thể lớn hơn nhiều do phải theo dõi các giá trị bị va chạm.
Trao đổi: Bây giờ bạn biết cái gì rẻ và cái gì không và trong hoàn cảnh nào, bạn sẽ có thể thấy sự đánh đổi. Bộ lọc Bloom rất tuyệt nếu bạn muốn nhanh chóng phát hiện ra rằng một giá trị đã được nhìn thấy trước đó, nhưng có thể sống với dương tính giả. Mặt khác, bạn có thể chọn bản đồ băm nếu bạn muốn đảm bảo tính chính xác ở mức giá không thể đánh giá chính xác thời gian chạy của bạn, nhưng có thể chấp nhận các trường hợp thoái hóa thỉnh thoảng có thể chậm hơn nhiều so với mức trung bình.
Tương tự, nếu bạn ở trong môi trường bộ nhớ hạn chế, bạn có thể muốn sử dụng các bộ lọc nở để đảm bảo sử dụng bộ nhớ của chúng.