PHÉP BIẾN ĐỔI KHÓA HÀM BĂM
Băm phương pháp rất thích hợp để cài đặt tập hợp số phần tử lớn và thời
gian cần thiết để thực hiện các phép toán từ điển, ngay cả trong trường hợp xấu
nhất, là tỉ lệ với cỡ của tập hợp.
Chúng ta sđề cập tới hai phương pháp m khác nhau. Một gọi băm mcho
phép sdụng một không gian không hạn chế để lưu giữ các phần tử của tập hợp.
Phương pháp băm khác được gọi băm đóng sử dụng một không gian cố định do
đó tập hợp được cài đặt phải có cỡ vượt qua không gian cho phép
$1. Khái niệm băm và hàm băm.
1.1. Băm mở và hàm băm.
a. Băm mở. Nội dung bản của băm mlà phân chia tập hợp đã cho tnh một
scố định các lớp. Chẳng hạn ta muốn phân thành N lớp được đánh số 0,1,..,N-1.
Ta sdụng mảng T với chỉ số chạy từ 0 đến N-1. Mối thành phần T[i] cúa mảng
được nói đến như một rổ đựng c phần tử của tập hợp thuộc lớp thứ i. Các phần
tcủa tập hợp thuộc mỗi lớp tổ chức dưới dạng một danh sách liên kết. Do T[i] sẽ
chứa con trỏ trỏ đến danh sách của lớp i.
b. Bảng băm. Ta gọi mảng T mà mỗi phần tử của nó như là một rổ đựng các phần
tử của tập hợp thuộc lớp tương ứng là bảng băm.
Việc phân chia các phần tử của tập hợp vào các lớp được thực hiện bởi hàm m
h.
c. Hàm băm. Nếu x là một giá tr khoá của phần tử nào đó của tập hợp thì h(x)
ch số nào đó của mảng T và ta gọi h(x) là giá trị băm (hash value) của x. Như vậy h
ánh xạ từ tập hợp các khoá K vào tập hợp { 0,1,…,N-1}.
$.2. Các phương pháp lựa chọn, thiết kế hàm băm và giải quyết va chạm.
2.1. Các phương pháp lựa chọn, thiết kế hàm băm
hai tiêu chuẩn chính đlựa chọn hàm băm. Trước hết phải cho phép nh
được ddàng nhanh chóng giá tr băm của mỗi khoá. Thhai, phải phân bố
đều các khóa vào các rổ. Trên thực tế tiêu chuẩn thứ hai rất khó được thực hiện.
Sau đây chúng ta đưa ra một số phương pháp thiết kế hàmm.
a. Phương pháp cắt bỏ.
Giả sử khoá là số nguyên (nếu khoá không phải là s nguyên, ta xét đến các mã s
của chúng). Ta sbđi một phần nào đó của khóa, và lấy phần còn lại lám gtr
băm của khoá. Chẳng hạn nếu khoá là các số nguyên gồm 10 chữ số và bảng băm
gồm 1000 thành phần, khi đó ta thể lấy chữ số thứ nhất, thứ ba và thbảy từ
bên trái làm giá trị băm. Ví dụ: h(7103592810) = 720.
Phương pháp cắt bỏ rất đơn giản nhưng nó thường không phân bố đều các khoá.
b. Phương pháp gấp.
Gisử khoá là snguyên. Ta phân chia khóa thành một số phần, sau đó kết hợp
các phần lại bằng một cách nào đó (phép cộng hoặc phép nhân) để nhận giá tr
băm. Nếu khlà snguyên 10 chữ số ta phân thànhc nhóm ba ba hai hai ch
stừ bên trái, cộng các nhóm với nhau sau đó cắt cụt nếu cần thiết, ta sẽ nhận
được giá trị của hàm m. dụ: số 7103592810 được biến đổi thành
710+359+28+10 = 1107, do đó ta có giá trị băm là 107.
Vì mọi thông tin trong khoá đều được phản ánh vào giá trị băm, nên phương pháp gấp
cho phân bố đều các khoá hơn phương pháp cắt bỏ.
c. Phương pháp sử dụng phép toán lấy dư.
Gisử khoá là snguyên ta muốn chia tập hợp các khoá thành n lp. Chia số
nguyên cho n rồi lấy phần làm g trị m. Điều này trong Pascal được thực
hiện bằng phép toán mod. Tính phân bố đều các khoá của hàm băm được xác định
bằng phương pháp này phụ thuộc nhiều vào vic chọn n. Tốt nhất chọn n là s
nguyên tố. Chẳng hạn thay cho việc chọn n = 1000 ta schọn n = 997 hoặc n =
1009.
Ví dụ viết một hàmm trong Pascal để băm các khoá là các xâu kí tự có độ dài 10
thành các giá trị từ 0…n-1.
Type keytype = string[10];
Function h(x: keytype):0..n-1;
Var
i, sum:integer ;
Begin
Sum:=0;
For i=1 to 10 do
Sum=sum + ord(x[i]);
h:= sum mod n;
end.
Trong hàm m trên, ta đã chuyển đổi các xâu tự thánh các số nguyên bng
cách lấy tổng số của các mã s của từng kí tự trong xâu dùng hàm ord(c) để lấy mã
số của kí tự c.
2.2. Bng băm đóng.
Trong bảng băm mở, mỗi thành phần T[i] của bảng lưu trữ con trỏ trỏ tới danh sách
các phn tử của tập hợp được đưa vào lớp thứ i (i = 0,…,N-1).
a. Băm đóng. Khác với bảng băm mở, trong bảng băm đóng, mỗi phần tử của tập
lưu giữ trong chính các thành phần T[i] của mảng. Do đó ta thể khai báo kiểu dữ
liêụ từ điển được cài đặt bởi bảng băm đóng như sau:
0
1
2
Type Dictionary = array [0..N-1] of keytype;
Keytype là kiểu dữ liệu của khoá của các phần tử trong từ điển.
2.3. Phân tích, đánh giá và minh họa phương pháp băm.
a. Phân tich đánh giá. Trong tất cả những thuật toán được xét từ trước tới nay, việc
định vị một mục được xác định bởi một dãy các so sánh. Trong mỗi trường hợp,
mục cần tìm được so sánh nhiều lần với c mục những vị trí o đó trong cấu
trúc. Đối với nhóm n mục, phép tìm kiếm tuyến tính đòi hỏi O(n) lần so nh, trong
khi đó phép tìm kiếm nhị phân chỉ cần O(log n) lần so sánh. Trong một số trường
hợp, những thuật toàn này thực hiện còn qchậm. dụ, bảng các hiệu được
lập bởi bộ dịch lưu trữ các định danh và những thông tin về chúng. Vận tốc xây
dựng và tìm kiếm trong bảng này quyết định vận tốc dịch. Một cấu trúc dữ liệu thực
hiện tìm kiếm nhanh hơn, được gọi là bảng băm (hash T), trong đó vtrí cuả một
mục được xác định trực tiếp bằng một hàm của chính nó chứ không phải bằng một
dãy các so sánh thvà sai (trial-and-error). Thời gian gian cần thiết để định vị một
mục trong bảng băm trong trường hợp tốt nhất là O(1), nghĩa là là một hằng số
và không phụ thuộc vào số các mục được lưu trữ.
b. dminh họa. Để minh hoạ, giả sử rằng cần lưu trữ 25 số nguyên trên đoạn
0..999 trong bng m. thể cài đặt bảng m này bằng một mảng T các số
nguyên được đánh chỉ số trên đoạn 0..999, trong đó mỗi phần tử của mảng được
khởi động tại một g trị câm o đó, chẳng hạn như tại 1. Nếu ta dùng mỗi số
nguyên i trong tập hợp đó làm chsố, nghĩa là nếu ta lưu trữ i trong T[i], ta thể
định vị một số nguyên number cho trước ch bằng cách kiểm tra T[number]
=number hay không. Hàm h được định nghĩa bởi h(i)=i xác định vị trí của mục i
trong bảng băm.
m m trong vị dnày thực hiện tìm kiếm một ch lý tưởng vì thời gian cần
thiết để tìm kiếm một g trị cho trước trong báng là hằng số; chỉ cn thử một vị trí.
Như vậy, đnày hiêu quvề tính thời gian, nhưng không hiệu quả về không
gian, ch25 trong số 1000 vị trí khả dĩ được dùng để lưu trư các mục còn 975 vt
còn lại không được dùng do đó đã lãng phí 97,5% không gian, chỉ dùng 2,5%.
thlưu trữ 25 giá trị 25 vị t ta thể sử dụng tốt hơn bằng ch dùng
mảng T được đánh chsố trên đoạn t0 đến 24. nhiên là không thdùng hàm
băm ban đầu h(i)=i được nữa. Thay vào đó ta có thể dùng: h(i)=i mod 25
m này luôn luôn miền giá trị là nhng số nguyên trên đoạn từ 0 đến 24.
Như vậy số nguyên 52 sđược lưu trT[2] vì h(52)= 52 mod 25 = 2. Tương tự
với các snguyên 129; 500 ; 73; 49 sđược lưu tại các vị trí 4, 0, 23 và 24 theo
thứ tự đó.
T[0]
T[1]
T[2]
T[3]
T[4]
T[5]
.
.
T[23]
T[24]
Với dụ trên nếu lấy hàm h[i]:=i mod 25 t s xẩy ra hiện tượng gọi là s va
chạm. vì nếu 77 được lưu trữ, sẽ được đặt vào v trí h(77)= 77 mod 25 = 2,
nhưng vị trí này đã bchiếm bởi 52. Cũng bằng cách đó, nhiều giá trị khác thể
trùng vào một vị trí cho trước,ví dụ,2,27,102 và trong thực tế tất cả các số nguyên
dạng 25k + 2 đều được lưu trữ tại v trí 2. nhiên là cần phải một cách nào đó
để giải quyết những va chạm này.
$3. Các phương pháp xử lý va chạm.
3.1.Phương pháp thăm dò tuyến tính.
a. Nội dung. Trong đồ này, phép tuyến tính trong bảng bắt đầu từ chỗ va
chạm và tiếp tục dò đền khi tìm thấy một khe trống thể lưu trữ được, va chạm
với giá trị 52 vị trí 2, một cách đơn giản ta đặt 77 giá trị 3; để chèn 102,
500
-1
52
-1
129
-1
.
.
273
49