Cài đặt từ điển bằng bảng băm đúng Định nghĩa bảng băm đúng :

Một phần của tài liệu Tài liệu Mảng và danh sách pptx (Trang 32 - 38)

2. Cài đặt từ điển bằng bảng băm

2.2.Cài đặt từ điển bằng bảng băm đúng Định nghĩa bảng băm đúng :

Bảng băm đúng lưu giữ cỏc phần tử của từ điển ngay trong mảng chứ khụng dựng mảng làm cỏc chỉ điểm đầu của cỏc danh sỏch liờn kết. Bucket thứ i chứa phần tử cú giỏ trị băm là i, nhưng vỡ cú thể cú nhiều phần tử cú cựng giỏ trị băm nờn ta sẽ gặp trường hợp sau: ta muốn đưa vào bucket i một phần tử x nhưng bucket này đó bị chiếm bởi một phần tử y nào đú (đụng độ). 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ày.

Giải quyết đụng độ :

Cỏch giải quyết đụng độ đú gọi là chiến lược băm lại (rehash strategy). Chiến lược băm lại là chọn tuần tự cỏc vị trớ h

1,..., h

k theo một cỏch nào đú cho tới khi gặp một vị trớ trống để

đặt x vào. Dóy h 1,..., h

k 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ộp thử cú dạng :

hi(x)=(h(x)+i) mod B

Vớ dụ B=8 và cỏc phần tử của từ điển là a,b,c,d cú giỏ trị băm lần lượt là: h(a)=3, h(b)=0, h(c)=4, h(d)=3. Ta muốn đưa cỏc phần tử này lần lượt vào bảng băm.

Khởi đầu bảng băm là rỗng, cú thể coi mỗi bucket chứa một giỏ trị đặc biệt Empty, Empty khụng bằng với bất kỳ một phần tử nào mà ta cú thể xột trong tập hợp cỏc phần tử muốn đưa vào bảng băm.

Ta đặt a vào bucket 3, b vào bucket 0, c vào bucket 4. Xột phần tử d, d cú h(d)=3 nhưng bucket 3 đó bị a chiếm ta tỡm vị trớ h1(x)= (h (x)+1) mod B = 4, vị trớ này cũng đó bị c chiếm, tiếp tục tỡm sang vị trớ h2 (x)= (h(x)+2) mod B= 5 đõy là một bucket rỗng ta đặt d vào

Hỡnh 18.1 Giải quyết đụng độ trong bảng băm đúng bằng chiến lược băm lại tuyến tớnh

Trong bảng băm đúng, phộp kiểm tra một thành viờn(thủ tục MEMBER (x,A)) phải xột dóy cỏc bucket h(x),h1(x),h2(x),... cho đến khi tỡm thấy x hoặc tỡm thấy một vị trớ trống. Bởi vỡ nếu hk(x) là vị trớ trống được gặp đầu tiờn thỡ x khụng thể được tỡm gặp ở một vị trớ nào xa hơn nữa. Tuy nhiờn, núi chung điều đú chỉ đỳng với trường hợp ta khụng hề xoỏ đi một phần tử nào trong bảng băm. Nếu chỳng ta chấp nhận phộp xoỏ thỡ chỳng ta qui ước rằng phần tử bị xúa sẽ được thay bởi một giỏ trị đặc biệt, gọi là Deleted, giỏ trị Deleted khụng bằng với bất kỳ một phần tử nào trong tập hợp đang xột vào nú cũng phải khỏc giỏ trị Empty. Empty cũng là một giỏ trị đặc biệt cho ta biết ụ trống.

Vớ dụ

- Tỡm phần tử e trong bảng băm trờn, giả sử h(e)=4. Chỳng ta tỡm kiếm e tại cỏc vị trớ 4,5,6. Bucket 6 là chứa Empty, vậy khụng cú e trong bảng băm.

- Tỡm d, vỡ h(d)=3 ta khởi đầu tại vị trớ này và duyệt qua cỏc bucket 4,5. Phần tử d được tỡm thấy tại bucket 5.

Sử dụng bảng băm đúng để cài đặt từ điển

Dưới đõy là khai bỏo và thủ tục cần thiết để cài đặt từ điển bằng bảng băm đúng. Để dễ dàng minh hoạ cỏc giỏ trị Deleted và Empty, giả sử rằng ta cần cài đặt từ điển gồm cỏc chuỗi 10 kớ tự. Ta cú thể qui ước:

Empty là chuỗi 10 dấu + và Deleted là chuỗi 10 dấu *.

Khai bỏo

#define B 100

#define Deleted -1000//Gia dinh gia tri cho o da bi xoa

#define Empty 1000 //Gia dinh gia tri cho o chua su dung typedef int ElementType;

typedef int Dictionary [B];

Tạo hàm băm int H (ElementType X)] { return X%B; } Tạo tự điển rỗng

// Tao tu dien rong

void MakeNullDic(Dictionary D){ for (int i=0;i<B; i++)

D[i]=Empty; }

Kiểm tra sự tồn tại của phần tử trong tự điển

Hàm trả về giỏ tri 0 nếu phần tử X khụng tồn tại trong tự điển; Ngược lại, hàm trả về giỏ trị 1; (adsbygoogle = window.adsbygoogle || []).push({});

int Member(ElementType X, Dictionary D) {

Position init=H(X), i=0;

while ((i<B) && (D[i]!=Empty) && (D[i]!=X)) i++; return (D[i]==X);

}

Thờm phần tử vào tự điển

void InsertDic(ElementType X, Dictionary D) { int i=0,init;

if (FullDic(D))

printf("Bang bam day"); else

if (Member(X,D)==0) {

while((i<B)&&(D[(i+init)%B]!=Empty)&&(D[(i+init)%B]!=Deleted) )

i++;

D[(i+init)%B]=X;

printf("\n Vi tri de xen phan tu %d la %d\n",X,(i+init)%B); }

else

printf ("\nPhan tu da ton tai trong bang bam"); }

Xúa từ ra khỏi tự điển

void DeleteDic(ElementType X, Dictionary D) {

if (EmptyDic(D))

printf("\nBang bam rong!"); else { int i=0,init =H(X); while ((i<B)&&(D[(i+init)%B]!=X)&&(D[(i+init)%B]!=Deleted)) i++; if ( D[(i+init)%B]==X) D[(i+init)%B]=Deleted; } } 2. Cỏc phương phỏp xỏc định hàm băm Phương phỏp chia

"Lấy phần dư của giỏ trị khoỏ khi chia cho số bucket" . Tức là hàm băm cú dạng:

H(x)= x mod B

Phương phỏp này rừ ràng là rất đơn giản nhưng nú cú thể khụng cho kết quả ngẫu nhiờn lắm. Chẳng hạn B=1000 thỡ H(x) chỉ phụ thuộc vào ba số cuối cựng của khoỏ mà khụng phụ thuộc vào cỏc số đứng trước. Kết quả cú thể ngẫu nhiờn hơn nếu B là một số nguyờn tố.

Phương phỏp nhõn

"Lấy khoỏ nhõn với chớnh nú rồi chọn một số chữ số ở giữa làm kết quả của hàm băm". x x2 h(x) gồm 3 số ở giữa 5402 29181604 181 hoặc 816 0367 00134689 134 346 1246 01552516 552 525 2983 08898289 898 982

Vỡ cỏc chữ số ở giữa phụ thuộc vào tất cả cỏc chữ số cú mặt trong khoỏ do vậy cỏc khoỏ cú khỏc nhau đụi chỳt thỡ hàm băm cho kết quả khỏc nhau.

Phương phỏp tỏch

Đối với cỏc khoỏ 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 khoỏ ra thành nhiều đoạn cú kớch thước bằng nhau từ một đầu ( trừ đoạn tại đầu cuối ), núi chung mỗi đoạn cú độ dài bằng độ dài của kết quả hàm băm. Phõn đoạn cú thể là tỏch hoặc gấp:

a. Tỏch: tỏch khúa ra từng đoạn rồi xếp cỏc đoạn thành hàng được canh thẳng một đầu rồi cú thể cộng chỳng lại rồi ỏp dụng phương phỏp chia để cú kết quả băm.

vớ dụ: khoỏ 17046329 tỏch thành 329

046 017 (adsbygoogle = window.adsbygoogle || []).push({});

cộng lại ta được 392. 392 mod 1000 = 392 là kết quả băm khoỏ đó cho.

b. Gấp: gấp khoỏ lại theo một cỏch nào đú, cú thể tương tự như gấp giấy, cỏc chữ số cựng nằm tại một vị trớ sau khi gấp dược xếp lại thẳng hàng với nhau rồi cú thể cộng lại rồi ỏp dụng phương phỏp chia (mod) để cho kết quả băm

Vớ dụ: khoỏ 17046329 gấp hai biờn vào ta cú 932

046 710

Bài 19: Thảo luận về vai trũ của cỏc cấu trỳc dữ liệu trong thiết kế chương trỡnh

19.1. Thảo luận về vai trũ của cỏc cấu trỳc dữ liệu trong thiết kế chương trỡnh Trong khoa học mỏy tớnh, cấu trỳc dữ liệu là một cỏch lưu dữ liệu trong mỏy tớnh sao cho nú cú thể được sử dụng một cỏch hiệu quả. Thụng thường, một cấu trỳc dữ liệu được chọn cẩn thận sẽ cho phộp thực hiện thuật toỏn hiệu quả hơn. Việc chọn cấu trỳc dữ liệu thường bắt đầu từ chọn một cấu trỳc dữ liệu trừu tượng. Một cấu trỳc dữ liệu được thiết kế tốt cho phộp thực hiện nhiều phộp toỏn, sử dụng càng ớt tài nguyờn, thời gian xử lý và khụng gian bộ nhớ càng tốt. Cỏc cấu trỳc dữ liệu được triển khai bằng cỏch sử dụng cỏc kiểu dữ liệu, cỏc tham chiếu và cỏc phộp toỏn trờn đú được cung cấp bởi một ngụn ngữ lập trỡnh.

Mỗi loại cấu trỳc dữ liệu phự hợp với một vài loại ứng dụng khỏc nhau, một số cấu trỳc dữ liệu dành cho những cụng việc đặc biệt. Vớ dụ, cỏc B-tree đặc biệt phự hợp trong việc thiết kế cơ sở dữ liệu.

Trong thiết kế nhiều loại chương trỡnh, việc chọn cấu trỳc dữ liệu là vấn đề quan trọng. Kinh nghiệm trong việc xõy dựng cỏc hệ thúng lớn cho thấy khú khăn của việc triển khai chương trỡnh, chất lượng và hiệu năng của kết quả cuối cựng phụ thuộc rất nhiều vào việc chọn cấu trỳc dữ liệu tốt nhất. Sau khi cấu trỳc dữ liệu được chọn, người ta thường dễ nhận thấy thuật toỏn cần sử dụng. Đụi khi trỡnh tự cụng việc diễn ra theo thứ tự ngược lại: cấu trỳc dữ liệu được chọn do những bài toỏn quan trọng nhất định cú thuật toỏn chạy tốt nhất với một số cấu trỳc dữ liệu cụ thể. Trong cả hai trường hợp, việc lựa chọn cấu trỳc dữ liệu là rất quan trọng. Tri thức đú đó dẫn đến sự nổi lờn của nhiều ngụn ngữ lập trỡnh và phương phỏp thiết kế được hỡnh thức húa, mà trong đú, nhõn tố tổ chức quan trọng là cỏc cấu trỳc dữ liệu chứ khụng phải cỏc thuật toỏn. Đa số ngụn ngữ cú một tớnh năng thuộc dạng hệ thống module cho phộp cỏc cấu trỳc dữ liệu được tỏi sử dụng an toàn trong cỏc ứng dụng khỏc nhau, bằng cỏch dựng cỏc giao diện cú điều khiển để che cỏc chi tiết cài đặt đó được kiểm thử. Đặc biệt, cỏc ngụn ngữ lập trỡnh hướng đối tượng như C++ và Java sử dụng lớp (class) cho mục đớch này.

Vỡ cấu trỳc dữ liệu cú tớnh chất quyết định đối với cỏc chương trỡnh chuyờn nghiệp nờn cú rất nhiều hỗ trợ về cấu trỳc dữ liệu trong cỏc thư viện chuẩn của cỏc ngụn ngữ lập trỡnh hiện đại, vớ dụ thư viện mẫu chuẩn của C++, Java API, và Microsoft .NET Framework.

Cỏc cấu trỳc xõy dựng căn bản của hầu hết cỏc cấu trỳc dữ liệu là mảng (array), bản ghi (record), tổ hợp phõn biệt(?) (discriminated union), và tham chiếu

(reference). Vớ dụ, tham chiếu khả rỗng (cú thể cú giỏ trị null) là một kết hợp của tham chiếu và cấu trỳc discriminated union, và cấu trỳc dữ liệu liờn kết đơn giản

nhất, danh sỏch liờn kết, được xõy dựng từ cỏc bản ghi và cỏc tham chiếu khả rỗng.

19.2. Trao đổi về bài tập lớn.

Bài 20: Kiểm tra giữa kỳ

Một phần của tài liệu Tài liệu Mảng và danh sách pptx (Trang 32 - 38)