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

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

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

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

Băm mở là một mảng một chiều cú B phần tử cú chỉ số từ 0 đến B-1. Mỗi phần tử là một con trỏ, trỏ tới một danh sỏch liờn kết mà dữ liệu sẽ của từ điển sẽ được lưu trong cỏc danh sỏch liờn kết này. Mỗi danh sỏch được gọi là một Bucket (một danh sỏch cú chứa cỏc phần tử cú cựng giỏ trị hàm băm).

Hàm băm:

Hàm băm là một ỏnh xạ từ tập dữ liệu A đến cỏc số nguyờn 0..B-1 (h : A → 0..B-1); Theo đú giả sử x ≍ A thỡ h(x) là một số nguyờn 0≤h(x) ≤B-1. Cú nhiều cỏch để xõy dựng hàm băm, cỏch đơn giản nhất là ‘nguyờn húa x ‘ và sau đú lấy h(x) = x % B.

Vớ dụ : Cho tập hợp A = {1,5,7,2,4,15}

Bảng băm là mảng gồm 5 phần tử và hàm băm h(x) = x % 5; Ta cú bảng băm lưu trữ A như sau :

Hàm băm cú thể được thiết kế như sau

//Ham bam H(X)=X Mod B int H(ElementType X) {

return X%B; }

Dưới đõy là cỏc thủ tục cài đặt từ điển bằng bảng băm mở với giả thiết rằng cỏc phần tử trong từ điển cú kiểu ElementType và hàm băm là H.

Khai bỏo

#define B ...

typedef ... ElementType; typedef struct Node

{

ElementType Data; Node* Next;

};

typedef Node* Position;

typedef Position Dictionary[B];

Khởi tạo bảng băm mở rỗng

Lỳc này tất cả cỏc bucket là rỗng nờn ta gỏn tất cả cỏc con trỏ trỏ đến đầu cỏc danh sỏch trong mỗi bucket là NULL.

void MakeNullSet(Dictionary *D) {

for(int i=0;i<B;i++) (*D)[i]=NULL;

}

Kiểm tra một thành viờn trong từ điển được cài bằng bảng băm mở

Để kiểm tra xem một khoỏ x nào đú cú trong từ điển hay khụng, ta tớnh địa chỉ của nú trong bảng băm. Theo cấu trỳc của bảng băm thỡ khoỏ x sẽ nằm trong bucket được trỏ bởi D[h(x)], với h(x) là hàm băm. Như vậy để tỡm khoỏ x trước hết ta phải tớnh h(x) sau đú duyệt danh sỏch của bucket được trỏ bởi D[h(x)]. Giải thuật như sau:

int Member(ElementType X, Dictionary D) {

Position P; int Found=0; //Tim o muc H(X) P=D[H(X)];

//Duyet tren ds thu H(X) while((P!=NULL) && (!Found)) if (P->Data==X) Found=1; else P=P->Next;

return Found; }

Thờm một phần tử vào từ điển được cài bằng bảng băm mở

Để thờm một phần tử cú khoỏ x vào từ điển ta phải tớnh bucket chứa nú, tức là phải tớnh h(x). Phần tử cú khoỏ x sẽ được thờm vào bucket được trỏ bởi D[h(x)]. Vỡ ta khụng quan tõm đến thứ tự cỏc phần tử trong mỗi bucket nờn ta cú thể thờm phần tử mới ngay đầu bucket này. Giải thuật như sau:

void InsertSet(ElementType X, Dictionary *D) { int Bucket; Position P; if (!Member(X,*D)) { Bucket=H(X); P=(*D)[Bucket];

//Cap phat o nho moi cho *D[Bucket]

(*D)[Bucket] = (Node*)malloc(sizeof(Node)); (*D)[Bucket]->Data=X;

(*D)[Bucket]->Next=P; }

}

Xoỏ một phần tử trong từ điển được cài bằng bảng băm mở

Xoỏ một phần tử cú khoỏ x trong từ điển bao gồm việc tỡm ụ chứa khoỏ và xoỏ ụ này. Phần tử x, nếu cú trong từ điển, sẽ nằm ở bucket D[h(x)]. Cú hai trường hợp cần phõn biệt. Nếu x nằm ngay đầu bucket, sau khi xoỏ x thỡ phần tử kế tiếp sau x trong bucket sẽ trở thành đầu bucket. Nếu x khụng nằm ở đầu bucket thỡ ta duyệt bucket này để tỡm và xoỏ x. Trong trường hợp này ta phải định vị con trỏ duyệt tại "ụ trước" ụ chứa x để cập nhật lại con trỏ Next của ụ này. Giải thuật như sau:

{

int Bucket, Done; Position P,Q; Bucket=H(X);

// Neu danh sach ton tai if ((*D)[Bucket]!=NULL) {

// X o dau danh sach

if ((*D)[Bucket]->Data==X) { Q=(*D)[Bucket]; (*D)[Bucket]=(*D)[Bucket]->Next; free(Q); } else // Tim X { Done=0; P=(*D)[Bucket];

while ((P->Next!=NULL) && (!Done)) if (P->Next->Data==X) Done=1;

else P=P->Next; // Neu tim thay if (Done) { //Xoa P->Next Q=P->Next; P->Next=Q->Next; free(Q); } } } }

2.2. 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 27 - 32)