Tổng quan về bảng băm đơn giản
Là một trình làm mới, bảng băm là một cách để lưu trữ một giá trị dưới một khóa cụ thể trong cấu trúc dữ liệu. Chẳng hạn, tôi có thể lưu trữ giá trị "a"
dưới khóa 1
, và sau đó lấy lại nó bằng cách tra cứu khóa 1
trong bảng băm.
Ví dụ đơn giản nhất về bảng băm mà tôi có thể nghĩ ra khỏi đỉnh đầu là bảng băm chỉ có thể lưu trữ số nguyên, trong đó khóa cho mục nhập bảng băm cũng là giá trị được lưu trữ. Giả sử bảng của bạn có kích thước 8 và về cơ bản, đó là một mảng trong bộ nhớ:
---------------------------------
| | | | | | | | |
---------------------------------
0 1 2 3 4 5 6 7
Hàm băm
Các hàm băm cung cấp cho bạn một chỉ mục về nơi lưu trữ giá trị của bạn. Một hàm băm khá đơn giản cho bảng này sẽ là thêm 1 vào giá trị bạn muốn lưu trữ, sau đó sửa đổi nó bằng 8 (kích thước bảng). Nói cách khác, hàm băm của bạn là (n+1)%8
, n
số nguyên bạn muốn lưu trữ ở đâu.
Chèn
Nếu bạn muốn chèn một giá trị vào bảng băm này, bạn gọi hàm băm của mình (trong trường hợp này (n+1)%8
) trên giá trị bạn muốn chèn để cung cấp cho bạn một chỉ mục. Chẳng hạn, nếu chúng ta muốn chèn 14, chúng ta sẽ gọi (14 + 1) % 8
và lấy chỉ mục 7
, vì vậy chúng ta sẽ chèn giá trị đó vào chỉ mục 7
.
---------------------------------
| | | | | | | |14 |
---------------------------------
0 1 2 3 4 5 6 7
Tương tự, chúng ta có thể chèn 33, 82 và 191 như vậy:
---------------------------------
|191| |33 |82 | | | |14 |
---------------------------------
0 1 2 3 4 5 6 7
Va chạm
Nhưng điều gì xảy ra nếu chúng ta cố gắng chèn một cái gì đó sẽ va chạm với một mục? 2 nên đi theo chỉ mục 3
, nhưng nó được thực hiện bởi 82. Có nhiều cách để giải quyết vấn đề này, cách đơn giản nhất là gọi hàm băm của chúng ta nhiều lần cho đến khi chúng ta tìm thấy một khoảng trống.
Vì vậy, logic như sau:
- (2 + 1)% 8 = 3
- Chỉ số 3 đã đầy
- Cắm 3 trở lại vào chức năng băm của chúng tôi. ( 3 + 1)% 8 = 4 , trống.
- Đặt giá trị của chúng tôi vào chỉ số 4 .
Bây giờ bảng băm trông như thế này, với giá trị 2 được lưu trữ tại chỉ mục 4
.
---------------------------------
|191| |33 |82 |2 | | |14 |
---------------------------------
0 1 2 3 4 5 6 7
Nhược điểm của giải pháp này là khá sớm, bảng của chúng tôi sẽ đầy! Nếu bạn biết rằng kích thước dữ liệu của bạn bị giới hạn, thì đây không phải là vấn đề miễn là bảng của bạn đủ lớn để chứa tất cả các giá trị có thể. Nếu bạn muốn có thể giữ nhiều hơn, bạn có thể xử lý các va chạm khác nhau. Hãy quay trở lại nơi chúng ta đã ở trước khi chèn 2.
---------------------------------
|191| |33 |82 | | | |14 |
---------------------------------
0 1 2 3 4 5 6 7
Nếu bạn nhớ lại, (2+1)%8
cung cấp cho chúng tôi chỉ số 3
, được thực hiện. Nếu bạn không muốn bảng băm của mình lấp đầy, bạn có thể sử dụng từng chỉ mục bảng làm danh sách liên kết và nối vào danh sách tại chỉ mục đó. Vì vậy, thay vì gọi lại hàm băm, chúng ta chỉ cần thêm vào danh sách tại index 3
:
-----
| 2 |
---------------------------------
|191| |33 |82 | | | |14 |
---------------------------------
0 1 2 3 4 5 6 7
Danh sách này sau đó có thể phát triển nhiều như bộ nhớ sẽ cho phép. Tôi có thể chèn 18 và nó sẽ được thêm vào 2:
-----
|18 |
-----
| 2 |
---------------------------------
|191| |33 |82 | | | |14 |
---------------------------------
0 1 2 3 4 5 6 7
Tra cứu
Tra cứu các giá trị trong bảng băm của bạn rất nhanh, với điều kiện là bảng băm của bạn có kích thước khá lớn. Bạn chỉ cần gọi hàm băm của bạn và lấy chỉ mục. Giả sử bạn muốn xem 82 có trong bảng của bạn không. Hàm tra cứu sẽ gọi (82+1)%8
= 3
và xem mục trong chỉ mục 3
và trả lại cho bạn. Nếu bạn nhìn lên 16, chức năng tra cứu sẽ tìm trong chỉ mục 1
và thấy rằng nó không tồn tại.
Tra cứu cũng cần xử lý Va chạm!
Nếu bạn cố gắng tra cứu giá trị 2, bảng băm của bạn sẽ phải sử dụng logic va chạm tương tự mà nó đã sử dụng để lưu trữ dữ liệu như để truy xuất dữ liệu. Tùy thuộc vào cách thức hoạt động của bảng băm của bạn, bạn sẽ băm khóa nhiều lần cho đến khi bạn tìm thấy mục bạn đang tìm kiếm (hoặc tìm một khoảng trống), hoặc bạn sẽ lặp qua danh sách được liên kết của mình cho đến khi bạn tìm thấy mục (hoặc đã đến cuối danh sách)
Tóm lược
Vì vậy, bảng băm là một cách tốt để lưu trữ và truy cập các cặp khóa-giá trị một cách nhanh chóng. Trong ví dụ này, chúng tôi đã sử dụng cùng khóa với giá trị, nhưng trong bảng băm trong thế giới thực, các khóa không bị giới hạn. Các hàm băm sẽ hoạt động trên các khóa để tạo một chỉ mục và sau đó khóa / giá trị có thể được lưu trữ tại chỉ mục đó. Các bảng băm không thực sự có nghĩa là được lặp đi lặp lại, mặc dù có thể làm như vậy. Như bạn có thể thấy, các bảng băm có thể có nhiều khoảng trống và việc lặp qua chúng sẽ gây lãng phí thời gian. Ngay cả khi bảng băm có logic để bỏ qua các tra cứu không gian trống trong trình lặp của nó, bạn sẽ phù hợp hơn khi sử dụng cấu trúc dữ liệu được thiết kế cho các trình lặp, như các danh sách được liên kết.