V. CĐY TÌM KIẾM NHỊ PHĐN
3. Bảng băm đóng (Close Hash Table)
TOP Bảng băm đóng lưu giữ câc phần tử ngay trong mảng chứ không dùng mảng lăm câc chỉ điểm đầụ Ô thứ i của mảng chứa phần tử có giâ trị băm lă ị Nhưng có thể có nhiều phần tử có cùng giâ trị băm nín ta thường gặp trường hợp ta muốn đưa văo ô thứ i một phần tử nhưng ô năy đê bị chiếm bởi phần tử y năo đó. Như vậy, khi thiết kế một bảng băm đóng ta phải có câch để giải quyết sự đụng độ năỵ Câch giải quyết đụng độ được gọi lă chiến lược băm lạị Chiến lược băm lại lă chọn lần lượt câc vị trí h1, h2,..., hk cho đến khi gặp một vị trí trống để đặt x văọ Dêy h1, h2,..., hk được gọi lă dêy câc phĩp thử. Một chiến lược đơn giản lă băm lại tuyến tính, trong đó dêy câc phần tử có dạng : hi(x) = (h(x) + i) mod B
Ví dụ : Giả sử B = 8 vă câc phần tử của tự điển lă : a, b, c, d có câc giâ trị băm lần lượt lă 3, 0, 4, 3. Ta muốn đưa câc phần tử năy văo bảng băm.
ta không xóa bất kỳ phần tử năo trong bảng băm. Nếu ta chấp nhận phĩp xóa thì ta quy ước rằng phần tử bị xóa được thay bằng một giâ trị đặc biệt lă Deleted, giâ trị năy cũng không bằng với bất kỳ phần tử năo trong bảng băm kể cả Emptỵ
Ví dụ :
Tìm kiếm phần tử e trong bảng băm. Giả sử h(e) = 4, ta tiến hănh tìm kiếm tại câc vị trí 4, 5, 6. Vị trí 6 chứa empty vậy ta kết luận rằng không có phần tử e trong bảng băm.
Tìm kiếm phần tử d trong bảng băm. Giả sử h(d) = 3, ta tiến hănh tìm kiếm từ vị trí năy vă duyệt qua câc ô 4, 5 thì tìm thấy d.
Giả sử tự điển lă một tập hợp của câc chuuõi có độ dăi lă 10 ký tự. Ta có thể quy ước rằng Empty lă một chuỗi 10 dấu + vă deleteted lă một chuỗi gồm 10 dấu * . Giả sử hăm băm h(x) được lấy lă hăm băm cho ở ví dụ trước.
Khai bâo :
Const B = ... ; { số phần tử của bảng băm }
Type ElementType = String [10] ; { Kiểu phần tử trong tự điển } Index = 0 .. B-1 ;
Empty = ‘ + + + + + + + + + + ’ ; Deleteted = ‘ * * * * * * * * * * ’ ;
Dictionary = array [ 0 .. B-1] of ElementsType ; Thủ tục khởi tạo tự điển rỗng :
Procedure MakeNullDictionary (Var D : Dictionary);
Var i : Integer ; Begin
For i := 0 to B -1 do D[i] := Empty ; End; Hăm kiểm tra phần tử :
Function Member (x : ElementType; D : Dictionary) : Boolean;
Var start, i: Integer; Begin
Start := h(x) ; i := 0 ;
While ( i < B) and (D[start + i] mod B <> x) and (D[start + i] mod B <> Empty) do i := i + 1 ;
Member := (D[start + i] mod B = x) ;
End;
Thủ tục xen một phần tử văo tự điển :
Procedure InsertDictionary (x: ElementType; Var D : Dictionary);
Var start, i: Integer; Begin
Start := h(x) ; i := 0 ;
While ( i < B) and (D[start + i] mod B <> x) and (D[start + i] mod B <> Empty) and (D[start + i] mod B <> Deleted) do
i := i + 1 ;
If (D[start + i] mod B <> Empty) or (D[start + i] mod B <> Deleted) then D[start + i] mod B := x
Else Writeln (‘ x da ton tai hoac mang day ‘) ; End ;
Thủ tục xóa một phần tử khỏi tự điển :
Procedure DeleteDictionary (x: ElementType; Var D : Dictionary);
Var start, i: Integer; Begin
Start := h(x) ; i := 0 ;
While ( i < B) and (D[start + i] mod B <> x) and (D[start + i] mod B <> Empty) do i := i + 1 ;
If ( D[start + i] mod B = x ) then D[start + i] mod B := Deleteted
Else Writeln (‘ x khong co trong tu dien ‘); End ;
4. Ước lượng hiệu quả hăm băm TOP
Thời gian thực hiện câc phĩp toân trín bảng băm lă O(1+N/B), điều năy xảy ra khi hăm băm rải đều câc khóa, liệu một hăm băm như vậy có tồn tại hay không ? Ta thấy việc thiết kế hăm băm dựa trín câc tính toân số học để cho ra kết quả ngẫu nhiín. Một hăm băm căng ngẫu nhiín căng rêi đều câc phần tử. Mặt khâc, hăm băm phải đơn giản vì nếu hăm băm quâ phức tạp thì thời gian để băm một khóa lă lớn lăm ảnh hưởng chung đến hiệu quả của phương phâp. Câc phương phâp thiết kế hăm băm thường gặp lă:
ạ Phương phâp chia : Hăm băm có dạng H(x) = x Mod B
Phương phâp năy rõ răng lă đơn giản nhưng nó có thể cho kết quả không ngẫu nhiín lắm. Chẳng hạn nếu B = 103 thì H(x) chỉ phụ thuộc văo 3 số cuối cùng của khóa mă không phụ thuộc văo câc số đứng trước. Kết quả sẽ ngẫu nhiín hơn nếu ta chọn B lă số nguyín tố.
b. Phương phâp nhđn : Lấy 1 khóa nhđn với chính nó rồi lấy một số chữ số giữa lăm kết quả cho hăm băm.
Ví dụ :
c. Phương phâp phđn đoạn : Ðối với câc khóa dăi vă kích thước thay đổi người ta thường dùng phương phâp phđn đoạn. Tức lă phđn khóa thănh câc đoạn bằng nhau từ một đầu (trừ đoạn đầu cuối). Nói chung câc đoạn có độ dăi bằng độ dăi kết quả của hăm băm. Phđn đoạn có thể lă tâch hoặc gấp.
* Tâch : Khóa 17046329 được tâch thănh 071 | 064 | 329
=> 071 + 064 + 329 = 392. Sau đó lấy 392 Mod 1000 = 392 lă kết quả của khóạ * Gấp : Tương tự như gấp giấỵ Như 17046329 gấp 2 mĩp văo ta được: 923 + 046 + 710 = 1679 => 1679 Mod 1000 = 679.
5. Phđn tích bảng băm đóng TOP
ạ Hiện tượng gôm tụ : Trong bảng băm đóng thời gian thực hiện câc phĩp toân không chỉ phụ thuộc văo sự phđn phối của hăm băm mă còn phụ thuộc văo chiến lược băm lại khi giải quyết đụng độ. Chiến lược băm lại có thể lăm nảy sinh hiện tượng gôm tụ.
Ví dụ : Xĩt bảng băm có 10 vị trí (B=10) với chiến lược thử tuyến tính vă câc khóa có giâ trị băm như sau :
h(H) = 3 - Vị trí năy đê bị chiếm, ta thử sang câc vị trí 4, 5, 6, 7, 8 vă đưa H văo vị trí 8.
h(I) = 6 - Vị trí năy đê bị chiếm, ta thử sang câc vị trí 7, 8, 9 vă đưa I văo vị trí 9.
Rõ răng lă hăm băm của chúng ta cũng tương đối tốt, câc trường hợp đụng độ như C, D được giải quyết nhanh chóng. Nhưng việc băm lại phải mất thời gian khâ lđu với câc khóa H, I để so sânh chúng với câc khóa không có cùng giâ trị băm.
b. Chiến lược băm lại :
Như đê phđn tích ở trín, chiến lược giải quyết đụng độ như phĩp thử tuyến tính sẽ nảy sinh hiện tượng gôm tụ lăm ảnh hưởng chung đến hiệu quả của phương phâp. Ta biết rằng dêy câc phĩp thử được chọn trong phĩp thử tuyến tính lă : hi(x) = [h(x) + i] mod B. Tổng quât : hi(x) = [h(x) + G(i)] mod B với G(i) = ị
Vì G(i) = i lăm cho mỗi lần thử ta chỉ thử sang một ô kế tiếp do đó, câc phần tử bị gom tụ lạị Muốn khắc phục tình trạng năy ta chọn G(i) sao cho có thể chọn được câc vị trí xa hơn.
Ví dụ : Nếu ta dùng G (i) = C.i, với C>1. Chẳng hạn B = 8, C = 3, H(x) = 4 thì câc phĩp thử của chúng ta sẽ thực hiện lần lượt tại câc vị trí 4, 7, 2, 5, 0, 3, 6 vă 1.
Nếu B vă C có ước số chung lớn hơn 1 thì chiến lược năy sẽ không thănh công vì ta không thể duyệt qua tất cả câc ô để tìm vị trí trống. Chẳng hạn: B = 8, C = 2, H(x) = 4 thì ta chỉ có thể duyệt qua câc ô chẳn.
Chiến lược chọn G(i) = i2 được gọi lă phĩp thử cầu phương. Hi = (H(x) + i2) Mod B c. Xđy dựng lại hăm băm : Nếu ta dùng bảng băm mở thì thời gian trung bình phải mất cho câc phĩp toân lă N/B. Tỷ số năy sẽ lớn nếu N >> B. Nếu ta dùng bảng băm đóng thì thời gian trung bình cho câc phĩp toân tăng lín khâ nhanh khi bảng băm gần đầy (N/B -> 1). Ðể khắc phục nhược điểm đó ta có thể xđy dựng bảng băm mới có kích thước lớn hơn kích thước của bảng băm cũ rồi đưa câc phần tử của bảng băm cũ văo bảng băm mớị