3. CÁC PHƯƠNG PHÁP GIẢI QUYẾT ĐỤNG ĐỘ
khai bao mang HASHTABLE chua M con tro dau cua MHASHTABLE
--- */typedef PHNODE HASHTABLE[M]; typedef PHNODE HASHTABLE[M];
b.Cỏc phộp toỏn
Hàm băm
Giả sử chỳng ta chọn hàm băm dạng %: f(key)=key % M.
int HF (int key) {
return (key % M); }
Chỳng ta cú thể dựng một hàm băm bất kỡ thay cho hàm băm dạng
% trờn.
Phộp toỏn khởi tạo bảng băm
Khởi động cỏc HASHTABLẸ
{
for (int i=0;<M;i++); HASHTABLE[i]=NULL; }
Phộp toỏn kiểm tra bảng băm rỗng HASHTABLE[i]
Kiểm tra HASHTABLE[i] cú bị rỗng khụng?
int emptyHASHTABLE (int i) {
return(HASHTABLE[i] ==NULL ?1 :0); }
Phộp toỏn toàn bộ bảng băm rỗng
Kiểm tra bảng băm cú rỗng khụng?
int empty( )
for (int i = 0;i<M;i++)
if(HASHTABLE[i] !=NULL) return 0;
return 1 }
Phộp toỏn thờm vào
Thờm phần tử cú khúa k vào bảng băm.
Giả sử cỏc phần tử trờn cỏc HASHTABLE là cú thứ tự để thờm một
phần tử khúa k vào bảng băm trước tiờn chỳng ta xỏc định
HASHTABLE phự hợp, sau đú dựng phộp toỏn place của danh sỏch
liờn kết để đặt phần tử vào vi trớ phự hợp trờn HASHTABLẸ void insert(int k)
{
int i= HF(k)
InsertList(HASHTABLE[i],k); //phộp toỏn thờm khoỏ k vào danh sach lien ket HASHTABLE[i]
}
Phộp toỏn loại bỏ
Xúa phần tử cú khúa k trong bảng băm.
Giả sử cỏc phần tử trờn cỏc HASHTABLE là cú thứ tự, để xúa một
phần tử khúa k trong bảng băm cần thực hiện:
- Xỏcđịnh HASHTABLE phự hợp
- Tỡm phần tử để xúa trong HASHTABLE đó được xỏc định,
nếu tỡm thấy phần tử cần xúa thỡ loại bỏ phần tử theo cỏc
phộp toỏn tương tự loại bỏ một phần tử trong danh sỏch liờn kết.
void remove ( int k) { int b; PHNODE q, p; b = HF(k); p = hashHASHTABLE(b); q=p;
while(p !=NULL && p->key !=k) {
q=p; p=p->next; }
else if (p == HASHTABLE [b]) pop(b);
//Tac vu pop cua danh sach lien ket else
delafter(q);
/*tac vu delafter cua danh sach lien ket*/ }
Phộp toỏn xoỏ HASHTABLE[i]
Xúa tất cả cỏc phần tử trong HASHTABLE b.
void clearHASHTABLE (int b) {
PHNODE p,q;
//q la nut truoc,p la nut sau q = NULL; p = HASHTABLE[b]; while(p !=NULL) { q = p; p=p->next; freenode(q); }
HASHTABLE[b] = NULL; //khoi dong lai butket b }
Phộp toỏn xoỏ toàn bộ bảng băm
Xúa tất cả cỏc phần tử trong bảng băm.
void clear( ) { int b; for (b = 0; b<M ; b++) clearHASHTABLE(b); }
Phộp toỏn duyệt HASHTABLE[i]
Duyệt cỏc phần tử trong HASHTABLE b.
void traverseHASHTABLE (int b) { PHNODE p; p= HASHTABLE[b]; while (p !=NULL) { printf(“%3d”, p->key); p= p->next; } }
Phộp toỏn duyệt toàn bộ bảng băm
Duyệt toàn bộ bảng băm.
void traverse( ) {
int b;
{ printf(“\nButket %d:”,b); printf(“\nButket %d:”,b); traverseHASHTABLE(b); } } Phộp toỏn tỡm kiếm
Tỡm kiếm một phần tử trong bảng băm, nếu khụng tỡm thấy hàm này trả về hàm NULL, nếu tỡm thấy hàm này trả về con trả chỉ tỡm phần
tử tỡm thấỵ
PHNODE p; int b; b = HF (k);
p = HASHTABLE[b];
while(k > p->key && p !=NULL) p=p->next;
if (p == NULL | | k !=p->key) // khong tim thay return(NULL);
else //tim thay return(p); }
Nhận xột bảng băm dựng phương phỏp nối kết trực tiếp
Bảng băm dựng phương phỏp nối kết trực tiếp sẽ ”băm” n phần tử
vào danh sỏch liờn kết (M HASHTABLE).
Để tốc độ thực hiện cỏc phộp toỏn trờn bảng hiệu quả thỡ cần chọn
hàm băm sao cho băm đều n phần tử của bảng băm cho M HASHTABLE, lỳc này trung bỡnh mỗi HASHTABLE sẽ cú n/M
phần tử. Chẳng hạn, phộp toỏn search sẽ thực hiện việc tỡm kiếm
tuyến tớnh trờn HASHTABLE nờn thời gian tỡm kiếm lỳc này cú bậc
0 (n/M) – nghĩa là, nhanh gấp n lần so với việc tỡm kiếm trờn một
danh sỏch liờn kết cú n phần tử.
Nếu chọn M càng lớn thỡ tốc độ thực hiện cỏc phộp toỏn trờn bảng
băm càng nhanh, tuy nhiờn lại càng dựng nhiều bộ nhớ. Do vậy, cần điều chỉnh M để dung hũa giữa tốc độ truy xuất và dung lượng bộ
nhớ.
Nếu chọn M = n thỡ năng xuất tươngđương với truy xất trờn mảng (cú bậc O(1)), tuy nhiờn tốn nhiều bộ nhớ.
Nếu chọn M =n /k(k =2,3,4,…) thỡ ớt tốn bộ nhớ hơn k lần,
nhưng tốc độ chậm đi k lần.
Chương trỡnh minh họa
#include <stdiọh> #include <stdlib.h> #include <coniọh> #include <alloc.h> #define TRUE 1 #definr FALSE 0 #define M 10 struct nodes { int key;
struct nodes *next; };
typedef struct nodes *PHNODE; PHNODE HASHTABLE[M];
//tac vu getnode(void) {
PHNODE p;
p = (PHNODE) malloc(siseof(struct nodes)); return(p);
}
//Tac vu freenode: huy nut da cap phat void freenode(PHNODE p)
{
free(p); }
// Ham bam int HF(int key) {
return(key % M); }
//Khoi dong cac HASHTABLE void initHASHTABLE( ) { int b; for (b = 0 ;b < M;b+) HASHTABLE[b] = NULL; }
//Tac vu emptyHASHTABLE; kiem tra butket b co rong khong int emptyHASHTABLE (int b)
{
return(HASHTABLE[b] == NULL? TRUE :FALSE); }
//Tac vu empty: kiem tra bang bam co ranh khong int empty( ) { int b; for (b=0;b<M;b++) if(HASHTABLE[b]!=NULL) return(FALSE); return(TRUE); }
//Tac vu push; them nut moi vao au HASHTABLE b void push(int b,int x)
{ PHNODE p; PHNODE p; p = getnode( ); p-> key = x; p-> next =HASHTABLE[b]; HASHTABLE[b] = p; }
//Tac vu pop: xoa nut o dau HASHTABLE b int pop(int b)
{
PHNODE p; int k;
int (emptyHASHTABLE (b)) {
printf(“\nHASHTABLE%d rong,khong xoa nut duoc “,b); return(0);
}
p = HASHTABLE[b]; //nut can xoa la nut dau butket b k =p->key; //k la noi dung nut bi xoa
HASHTABLE[b] = p->next; freenode(p);
return(k); }
//Tac vu insafter: them nut moi vao HASHTABLE sau nut p void insafter(PHNODE q, int k)
{
PHNODE q; if (p == NULL)
printf(“khong them nut moi duoc”); else { q = getnode( ); q->key = k; q-> key= p->next p->next=q; } }
//Tac vu delafter: Xoa nut trong HASHTABLE trong nut p int delafter(PHNODE q)
{
PHNODE q; int k;
if(p==NULL | | p->next == NULL) {
printf (“khong xoa nut duoc”); return (0); }
q=p->next; // q chi nut can xoa k =q ->key; //k la noi dung nut bi xoa p->next = q =next;
freenode(q); return(k); }
//Tac vu place: tac vu nay chi su dung khi them nut vao HASHTABLE da co thu tu
void place(int b,int k) {
PHNODE p; q; //q la nut truoc, p la nut sau q = NULL;
for(p = HASHTABLE[b]; p!=NULL && k > p->key; p = p->next)
q=p;
if (q == NULL) //them nut vao dau butket push(b,k);
else
insafter (q, k); }
//Tac vu insert; them nut co khoa k vao bang bam void insert(int k)
{
int b; b = HF(k);
place(b, k);//tac vu place cua danh sach lien ket*/ }
//Tac vu remove : xoa nut co khoa k trong bang bam void remove (int k)
{ int b; int b; PHNODE p, q; b=HF(k); p=HASHTABLE[p]; q=p;
while(p !=NULL && p->key !=) {
q=p; p=p->next; }
if (p == NULL)
printf(“\n Khong co nut co khoa %d”, k); else
if(p == HASHTABLE[b]) pop(b);
/*tac vu pop cua dann sach lien ket*/ else
delafter(q);
/*tac vu delafter cua danh sach lien ket*/ }
//Tac vu clearHASHTABLE; xoa tat ca cac nut trong HASHTABLE b void clearHASHTABLE (int b)
{
PHNODE p, q; // q la nut truoc , p la nut sau q=NULL; p=buket[b]; while(p !=NULL) { q=p; p=p->next;
freenode[b] = NULL;//khoi dong HASHTABLE b }
}
//Tac vu clear: xoa tat ca cac nut trong bang bam void clear( ) { int b; for b=0; b<M; b++) clearHASHTABLE(b); }
//Tac vu traverseHASHTABLE: duyet HASHTABLE b void traversebuket(int b) { PHNODE p; p=HASHTABLE[b]; while (p !=NULL) { printf(“%3d”,p->key); p=p->next; } }
//Tac vu traverse: duyet bang ham void traverse( ) { int b; for (b=0;b<M; b++) { printf(“\nHASHTABLE %d:”,b); traverseHASHTABLE(b); } } /* --- Tac vu search: tim kiem mot nut trong bang bam, neu khong tim thay ham nay tra ve tri –1, neu tim thay ham
Tra ve 0 ---*/ int search(int k) { PHNODE p; int b; b = HF(k); p = HASHTABLE[b];
while(k >p->key && p !=NULL) p = =->next;
if(p== NULL || k!=p->key) //khong tim thay return(-1);
else // tim thay }
/*---Chuong trinh chinh Chuong trinh chinh
--- */Void main( ) Void main( ) { intb,key,i,n,chucnang; char c; clrscr();
initHASHTABLE(); //khoi dong M HASHTABLE cua bang bam do
{
//Menu chinh cua chuong trinh
printf(“\n\Cac chuc nang cua chuong trinh:\n”); printf(“\1:Them mot nut vao bang bam\n”);
printf(“\2:Them ngau nhien nhieu nut vao bang bam\n”); printf(“\3: Xoa nut trong bang bam\n”);
printf(“\5: Duyet bang bam\n”);
printf(“\6: Tỡm kiem tren bang bam\n”); printf(“\0:Ket thuc chuong trinh\n”); printf(“\n Chuc nang ban chon:”); scanf(“&d”,& chuc nang);
swhich(chuc nang) { case 1:
{ printf(“\nTHEM MOT NUT VAO BANG BAM”); printf(“\ Khoa cua nut moi:”);
scanf(“%d;,&key); insert(key); break; }
case 2:
{ printf(“\nTHEM NGAU HIEN NHIEU NUT VAO BANG BAM”); printf(“\n Ban muon them bao nhieu nut:”);
scanf(“%d”,&n); for (i=0;i<n;i++) { key = random(100); insert(key); } break; } case 3: {
printf(“\nXoa TREN BANG BAM”); printf(“\n khoa cua nut can xoa:”); scanf(“%d”,&key); remove(key); break; } case 4: {
printf(“\nXoa TOAN BO BANG BAM”); printf(“\nban co chac chan khong (c/k):”); c=getch(); if(c== ‘c’ | | c == ‘c’) clear( ); break; } case 5: {
printf(“\n DUYET BANG BAM”); traverse( );
break; }
case 6: {
printf(“\nTIM KIEM TREN BANG BAM”); pintf(“\n Khao can tim:”);
scanf(“%d”,&key); b=search(key); if(b == -1)
printf(“ khong thay”); else
printf(“ Tim thay trong HASHTABLE d”,b); break;
}} }
while(chucnang !=0);
clear( ); //Xoa tat ca cac nut tren bang bam }