Có một số kỹ thuật đảm bảo rằng việc tra cứu sẽ luôn yêu cầu các thao tác O (1), ngay cả trong trường hợp xấu nhất.
Làm cách nào tôi có thể xác định liệu bảng băm có cơ hội có các hoạt động O (1) hay không và có thể sử dụng các kỹ thuật nào trên hàm băm của tôi không?
Trường hợp xấu nhất xảy ra khi một số kẻ tấn công độc hại (Mallory) cố tình cung cấp cho bạn dữ liệu mà Mallory đã chọn cụ thể để làm cho hệ thống chạy chậm.
Khi bạn đã chọn một số hàm băm cụ thể, có thể quá lạc quan khi cho rằng Mallory sẽ không bao giờ tìm ra hàm băm nào bạn đã chọn. Khi Mallory phát hiện ra hàm băm nào bạn đã chọn, nếu bạn cho phép Mallory cung cấp cho bạn nhiều dữ liệu được chèn vào bảng băm của bạn bằng hàm băm đó, thì bạn sẽ bị tiêu diệt: Mallory có thể nhanh chóng tạo ra hàng tỷ mục dữ liệu, băm chúng với Hàm băm để tìm mục dữ liệu nào có khả năng va chạm và sau đó cung cấp cho bạn hàng triệu mục dữ liệu có khả năng va chạm, dẫn đến việc tra cứu chạy chậm hơn O (1).
Tất cả các kỹ thuật đảm bảo "tra cứu O (1) ngay cả trong trường hợp xấu nhất" đều tránh được vấn đề này bằng cách thực hiện thêm một chút công việc trên mỗi lần chèn để đảm bảo rằng, trong tương lai, mọi tra cứu có thể có thể thành công trong thời gian O (1) . Cụ thể, chúng tôi giả định (trường hợp xấu nhất) rằng Mallory sẽ sớm phát hiện ra hàm băm nào chúng tôi đang sử dụng; nhưng anh ta chỉ có cơ hội chèn một vài mục dữ liệu trước khi chúng tôi chọn một hàm băm khác - băm bảng hoặc một số băm phổ quát khác - một mục mà chúng tôi đặc biệt chọn sao cho tất cả dữ liệu chúng tôi có thể tìm kiếm trong 2 hoặc 3 đầu dò - tức là O (1). Vì chúng tôi chọn ngẫu nhiên chức năng này, chúng tôi có thể khá chắc chắn rằng Mallory sẽ không biết chúng tôi đã chọn chức năng nào trong một thời gian. Ngay cả khi Malloryngay lập tức cung cấp cho chúng tôi dữ liệu rằng, ngay cả với hàm băm mới này, va chạm với dữ liệu trước đó, sau đó chúng tôi có thể chọn một hàm băm mới khác để sau khi thử lại, tất cả dữ liệu trước đây mà anh ấy và mọi người đã cung cấp cho chúng tôi có thể được xem trong 2 hoặc 3 đầu dò trong trường hợp xấu nhất - nghĩa là tra cứu O (1) trong trường hợp xấu nhất.
Thật dễ dàng để chọn ngẫu nhiên một hàm băm mới và thường xuyên kiểm tra lại toàn bộ bảng để đảm bảo rằng mỗi lần tra cứu luôn là O (1). Mặc dù điều này đảm bảo rằng mỗi lần tra cứu luôn là O (1), nhưng các kỹ thuật này, khi chèn mục thứ N vào bảng băm có chứa các mục N-1, đôi khi có thể cần thời gian O (N) cho lần chèn đó. Tuy nhiên, có thể thiết kế hệ thống sao cho ngay cả khi Mallory cố tình cung cấp cho bạn dữ liệu mới, bằng cách sử dụng hàm băm mới, va chạm với dữ liệu trước đó, hệ thống có thể chấp nhận nhiều mục từ Mallory và các mục khác trước khi cần thực hiện xây dựng lại toàn bộ O (N). Các kỹ thuật bảng băm chọn một chức năng mới và thử nghiệm lại để đảm bảo tra cứu O (1), ngay cả trong trường hợp xấu nhất, bao gồm:
- băm cuckoo đảm bảo rằng mỗi lần tra cứu khóa thành công với tối đa 2 phép tính băm và 2 lần tra cứu bảng.
- băm hopscotch đảm bảo rằng mỗi lần tra cứu khóa thành công sau khi kiểm tra các mục nhỏ H (có lẽ H = 32) liên tiếp trong bảng.
- băm hoàn hảo năng động - bài báo năm 1994 của Dietzfelbinger là bài đầu tiên tôi đọc đã chỉ ra rằng, mặc dù nó diễn tập "thường xuyên" để đảm bảo rằng mỗi lần tra cứu khóa luôn thành công với 2 phép tính băm và 2 lần tra cứu, điều đó là có thể để thực hiện một bản phát lại đầy đủ, hiếm khi mặc dù mỗi bản phát lại đầy đủ sử dụng thời gian O (n), chi phí trung bình dự kiến của việc chèn và xóa được khấu hao O (1).
Cấu trúc dữ liệu / Bảng băm