Từ 1 tới 6 trên tổng số 6 kết quả

Đề tài: Lý thuyết tìm kiếm | Bảng băm ( hash table )

  1. #1
    Ngày gia nhập
    08 2006
    Nơi ở
    Hải Phòng
    Bài viết
    218

    Mặc định Lý thuyết tìm kiếm | Bảng băm ( hash table )

    Bảng băm


    Nội dung
    1.1) Bảng băm
    1.2) Định nghĩa hàm băm
    1.3) Một số phương pháp xây dựng hàm băm
    1.4) Các phương pháp giải quyết đụng độ


    Các thuật toán tìm kiếm đều dựa vào việc so sánh giá trị khoá (Key) của phần tử cần tìm với các giá trị khoá trong tập các phần tử, thao tác này
    • Phụ thuộc kích thước của tập các phần tử
    • Thời gian tìm kiếm không nhanh do phải thực hiện nhiều phép so sánh có thể không cần thiết ( O(n), O(logn), …)
    => Có phương pháp lưu trữ nào cho phép thực hiện tìm kiếm với hiệu suất cao hơn không ( độ phức tạp hằng số)?

    1.1) Bảng băm (Hash Table)

    Ví dụ: Giả sử ta có một tập phần tử gồm các giá trị khoá bất kỳ được tổ chức lưu trữ dưới dạng bảng chỉ mục m phần tử như sau gọi là bảng truy xuất trực tiếp (Direct access table)

    • Phần tử có giá trị khoá k được lưu trữ tương ứng tại vị trí thứ k trong bảng chỉ mục
    • Để tìm kiếm một phần tử nào đó ta sẽ dựa vào khoá của nó và tra trong bảng chỉ mục, nếu tại vị trí đó có phần tử thì chính là phần tử cần tìm, nếu không có phần tử nào có nghĩa là phần tử cần tìm không có trong bảng chỉ mục
    • Thời gian tìm kiếm là hằng số O(1)
    Đây là dạng bảng băm cơ bản


    a. Mô tả dữ liệu
    Giả sử
    • K: tập các khoá (set of keys)
    • A: tập các địa chỉ (set of addresses
    • HF(k): hàm băm dùng để ánh xạ một khoá k từ tập các khoá K thành một địa chỉ tương ứng trong tập A.
    b. Các phép toán trên bảng băm
    • Khởi tạo (Initialize)
    • Kiểm tra rỗng (Empty)
    • Lấy kích thước của bảng băm (Size)
    • Tìm kiếm (Search)
    • Thêm mới phần tử (Insert)
    • Loại bỏ (Remove)
    • Sao chép (Copy)
    • Duyệt (Traverse)

    c. Phân loại bảng băm
    • Bảng băm đóng : mỗi khóa ứng với một địa chỉ, thời gian truy xuất là hằng số
    • Bảng băm mở : một số khóa có cùng địa chỉ, lúc này mỗi mục địa chỉ sẽ là một danh sách liên kết các phần tử có cùng địa chỉ, thời gian truy xuất có thể bị suy giảm đôi chút

    1.2) Định nghĩa hàm băm

    Là hàm biến đổi giá trị khoá (số, chuỗi…) thành địa chỉ, chỉ mục trong bảng băm

    Ví dụ : hàm băm biến đổi khoá dạng chuỗi gồm n kí tự thành 1 địa chỉ (số nguyên)
    C Code:
    1. int hashfunc( char *s, int n )
    2. {
    3.     int sum = 0;
    4.     while( n-- ) sum = sum + *s++;
    5.     return sum % 256;
    6. }
    Tính địa chỉ của khoá "AB" : hashfunc("AB",2) 131
    Tính địa chỉ của khoá "BA" : hashfunc("BA",2) 131
    Khi hàm băm 2 khoá vào cùng 1 địa chỉ thì gọi là đụng độ (Collision)
    Hàm băm tốt thỏa mãn các điều kiện sau:
    • Tính toán nhanh.
    • Các khoá được phân bố đều trong bảng.
    • Ít xảy ra đụng độ
    Đã được chỉnh sửa lần cuối bởi iamvtn : 04-02-2008 lúc 05:40 PM.

  2. #2
    Ngày gia nhập
    08 2006
    Nơi ở
    Hải Phòng
    Bài viết
    218

    1.3) Một số phương pháp xây dựng hàm băm
    a. Hàm băm dạng bảng tra:
    Hàm băm có thể tổ chức ở dạng bảng tra (còn gọi là bảng truy xuất) hoặc thông dụng nhất là ở dạng công thức.
    Ví dụ sau đây là bảng tra với khóa là bộ chữ cái, bảng băm có 26 địa chỉ từ 0 đến 25. Khóa a ứng với địa chỉ 0, khoá b ứng với địa chỉ 1,… , z ứng với địa chỉ 25.

    Hình 1.3 Hàm băm dạng bảng tra được tổ chức dưới dạng danh sách kề.

    b. Hàm băm sử dụng phương pháp chia
    • Dùng số dư:
    h(k) = k mod m
    k là khoá, m là kích thước của bảng.
    vấn đề chọn giá trị m
    • Nếu chọn m= 2n thông thường không tốt vì h(k) = k mod 2n sẽ chọn cùng n bits thấp của k nên chọn m là nguyên tố (tốt) gần với 2n
    Ví dụ: Ta có tập khoá là các giá trị số gồm 3 chữ số, và vùng nhớ cho bảng địa chỉ có khoảng 100 mục, như vậy ta sẽ lấy hai số cuối của khoá để làm địa chỉ theo phép chia lấy dư cho 100 : chẳng hạn 325 Mod 100 = 25
    Tuy nhiên ta nhận thấy nếu hàm băm dùng công thức như trên thì địa chỉ của khoá tính được chỉ căn cứ và 2 ký số cuối. Vì thế, để hàm băm có thể tính địa chỉ khoá một cách "ngẫu nhiên" hơn ta nên chọn m=97 thay vì 100

    c. Hàm băm sử dụng phương pháp nhân
    • Sử dụng công thức
    h(k) = floor(m (k A mod 1))
    k là khóa, m là kích thước bảng, A là hằng số: 0 < A < 1
    • Chọn m và A
    Ta thường chọn m = 2n
    Theo Knuth chọn A = 1/2(sqrt(5) -1) 0.618033987 được xem là tốt

    d. Dùng hàm băm phổ quát
    Một tập các hàm băm H là phổ quát (universal ) nếu hH và 2 khoá k, l ta có xác suất: Pr{h(k) = h(l)} <= 1/m ,• với m là kích thước bảng
    Để xác suất xảy ra đụng độ thấp, khởi tạo một tập các hàm băm H phổ quát và từ đó h được chọn ngẫu nhiên.

    Ví dụ: Giả sử nếu khoá là một số nguyên, dương và HK(key) là một số nguyên với một digit từ 0..9, Thế thì, hàm băm sẽ dùng toán tử modulo-10 để trả về giá trị tương ứng của một khoá. Chẳng hạn: nếu khoá=49 thì HF(49)=9.

  3. #3
    Ngày gia nhập
    08 2006
    Nơi ở
    Hải Phòng
    Bài viết
    218

    1.4) Một số phương pháp giải quyết sự đụng độ
    Người ta giải quyết sự đụng độ theo hai phương pháp: phương pháp nối kết và phương pháp băm lại.
    Giải quyết sự đụng độ bằng phương pháp nối kết (Chaining Method):
    Các phần tử bị băm vào cùng địa chỉ (các phần tử bị đụng độ) được gom thành một danh sách liên kết (gọi là một bucket).

    Cài đặt bảng băm dùng phương pháp nối kết trực tiếp :

    a. Khai báo cấu trúc bảng băm:
    #
    C Code:
    1. define M   100
    2. struct nodes
    3. {
    4. int key;
    5. struct nodes *next
    6. };
    C Code:
    1. //khai bao kieu con tro chi nut
    2. typedef struct nodes *NODEPTR
    3. /*
    4. khai bao mang bucket chua M con tro dau cua M bucket
    5. */
    6. NODEPTR bucket[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.
    C Code:
    1. int hashfunc (int key)
    2. {
    3. return (key % M);
    4. }
    Phép toán initbuckets:
    C Code:
    1. void initbuckets( )
    2. {
    3. int b;
    4. for (b=0;b<M;b++);
    5. bucket[b]=NULL;
    6. }
    Phép toán emmptybucket:
    C Code:
    1. int emptybucket (int b)
    2. {
    3. return(bucket[b] ==NULL ?TRUE :FALSE);
    4. }
    Phép toán emmpty:
    C Code:
    1. int empty( )
    2. {
    3. int b;
    4. for (b = 0;b<M;b++)
    5. if(bucket[b] !=NULL)  return(FALSE);
    6. return(TRUE);
    7. }
    Phép toán insert:
    C Code:
    1. void insert(int k)
    2. {
    3. int b;
    4. b= hashfunc(k)
    5. place(b,k); //tac vu place cua danh sach lien ket
    6. }
    Phép toán remove:
    C Code:
    1. void remove ( int k)
    2. {
    3. int b;
    4. NODEPTR q, p;
    5. b = hashfunc(k);
    6. p = hashbucket(k);
    7. q=p;
    8. while(p !=NULL && p->key !=k)
    9. {
    10.    q=p;
    11.    p=p->next;
    12. }
    13. if (p == NULL)
    14. printf("\n khong co nut co khoa %d" ,k);
    15. else
    16. if (p == bucket [b])   pop(b);
    17. //Tac vu pop cua danh sach lien ket
    18. else
    19. delafter(q);
    20. /*tac vu delafter cua danh sach lien ket*/
    21. }
    Phép toán clearbucket:
    Xóa tất cả các phần tử trong bucket b.
    C Code:
    1. void clearbucket (int b)
    2. {
    3. NODEPTR p,q;
    4. //q la nut truoc,p la nut sau
    5. q = NULL;
    6. p = bucket[b];
    7. while(p !=NULL)
    8. {
    9.     q = p;
    10.     p=p->next;
    11.     freenode(q);
    12. }
    13. bucket[b] = NULL; //khoi dong lai butket b
    14. }
    Phép toán clear:
    Xóa tất cả các phần tử trong bảng băm.
    C Code:
    1. void clear( )
    2. {
    3. int b;
    4. for (b = 0; b<M ; b++)
    5. clearbucket(b);
    6. }
    Phép toán traversebucket:
    Duyệt các phần tử trong bucket b.
    C Code:
    1. void traversebucket (int b)
    2. {
    3.  NODEPTR p;
    4. p= bucket[b];
    5. while (p !=NULL)
    6. {
    7. printf("%3d", p->key);
    8. p= p->next;
    9. }
    10. }
    Phép toán traverse:
    Duyệt toàn bộ bảng băm.
    C Code:
    1. void traverse( )
    2. {
    3. int b;
    4. for (b = 0;n<M; b++)
    5. {
    6. printf("\nButket %d:",b);
    7. traversebucket(b);
    8. }
    9. }
    Phép toán search:
    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ề giá trị NULL,nếu tìm thấy hàm này trả về con trỏ chỉ tìm phần tử tìm thấy.
    C Code:
    1. NODEPTR search(int k)
    2. {
    3. NODEPTR p;
    4. int b;
    5. b = hashfunc (k);
    6. p = bucket[b];
    7. while(k > p->key && p !=NULL)
    8. p=p->next;
    9. if (p == NULL | | k !=p->key)// khong tim thay
    10. return(NULL);
    11. else//tim thay
    12. // else //tim thay
    13. return(p);
    14. }

  4. #4
    Ngày gia nhập
    08 2006
    Nơi ở
    Hải Phòng
    Bài viết
    218

    Giải quyết sự đụng độ bằng phương pháp băm lại:

    • Phương pháp dò tuyến tính (Linear Probe)
    Nếu băm lần đầu bị xung đột thì băm lại lần 1, nếu bị xung đột nữa thì băm lai lần 2,… Quá trình băm lại diễn ra cho đến khi không còn xung đột nữa. Các phép băm lại (rehash function) thường sẽ chọn địa chỉ khác cho các phần tử.
    hi(key)=(h(key)+i) %M với h(key) là hàm băm chính của bảng băm

    Cài đặt bảng băm dùng phương pháp dò tuyến tính:

    a. Khai báo cấu trúc bảng băm:
    C Code:
    1. #define NULLKEY –1
    2. #define M 100
    3. /*
    4. M la so nut co tren bang bam,du de chua cac nut nhap vao bang bam
    5. */
    6. //khai bao cau truc mot nnut cua bang bam
    7. struct node
    8. {
    9. int key; //khoa cua nut tren bang bam
    10. };
    11. //Khai bao bang bam co M nut
    12. struct node hashtable[M];
    13. int NODEPTR;
    14. /*bien toan cuc chi so nut hien co tren bang bam*/
    b. Các tác vụ:
    Hàm băm:
    C Code:
    1. int hashfunc(int key)
    2. {
    3. return(key% M)
    4. }
    Phép toán khởi tạo (initialize):
    Khởi tạo bảng băm.
    Gán biến toàn cục N=0.
    C Code:
    1. void initialize( )
    2. {
    3. int i;
    4. for(i=0;i<M;i++)
    5. hashtable[i].key=NULLKEY;
    6. N=0;
    7. //so nut hien co khoi dong bang 0
    8. }
    Phép toán kiểm tra trống (empty):
    Kiểm tra bảng băm có trống hay không.
    C Code:
    1. int empty( );
    2. {
    3. return(N==0 ? TRUE:FALSE);
    4. }
    Phép toán kiểm tra đầy (full):
    Kiểm tra bảng băm đã đầy chưa.
    C Code:
    1. int full( )
    2. {
    3. return (N==M-1 ? TRUE: FALSE);
    4. }
    Lưu ý bảng băm đầy khi N=M-1, chúng ta nên dành ít nhất một phần tử trống trên bảng băm.

    Phép toán search:
    C Code:
    1. int search(int k)
    2. {
    3. int i;
    4. i=hashfunc(k);
    5. while(hashtable[i].key!=k && hashtable[i].key !=NULKEY)
    6. {
    7. //bam lai (theo phuong phap do tuyen tinh:fi(key)=f(key)+i) % M
    8. i=i+1;
    9. if(i>=M)
    10. i=i-M;
    11. }
    12. if(hashtable[i].key==k) //tim thay
    13. return(i);
    14. else
    15. //khong tim thay
    16. return(M);
    17. }
    Phép toán insert:
    Thêm phần tử có khoá k vào bảng băm.
    C Code:
    1. int insert(int k)
    2. {
    3. int i, j;
    4. if(full( ))
    5. {
    6. printf("\n Bang bam bi day khong them nut co khoa %d duoc",k);
    7. return;
    8. }
    9. i=hashfunc(k);
    10. while(hashtable[i].key !=NULLKEY)
    11. {
    12. //Bam lai (theo phuong phap do tuyen tinh)
    13. i ++;
    14. if(i >M)  i= i-M;
    15. }
    16. hashtable[i].key=k;
    17. N=N+1;
    18. return(i);
    19. }

  5. #5
    Ngày gia nhập
    08 2006
    Nơi ở
    Hải Phòng
    Bài viết
    218

    Bảng băm với phương pháp dò bậc hai (Quadratic Probing Method)

    - Hàm băm lại của phương pháp dò bậc hai là truy xuất các địa chỉ cách bậc 2. Hàm băm lại hàm i được biểu diễn bằng công thức sau:
    hi(key)=( h(key) + i2 ) % M
    với h(key) là hàm băm chính của bảng băm.
    Nếu đã dò đến cuối bảng thì trở về dò lại từ đầu bảng.
    Bảng băm với phương pháp do bậc hai nên chọn số địa chỉ M là số nguyên tố.

    Cài đặt bảng băm dùng phương pháp dò bậc hai:
    a. Khai báo cấu trúc bảng băm:

    C Code:
    1. #define NULLKEY –1
    2. #define M 101
    3. /* M la so nut co tren bang bam,du de chua cac nut nhap vao bang bam,chon M la so nguyen to
    4. */
    5. //Khai bao nut cua bang bam
    6. struct node
    7. {
    8. int key; //Khoa cua nut tren bang bam
    9. };
    10. //Khai bao bang bam co M nut
    11. struct node hashtable[M];
    12. int N;
    13. //Bien toan cuc chi so nut hien co tren bang bam
    b. Các tác vụ :
    Hàm băm:
    Giả sử chúng ta chọn hàm băm dạng%: f(key)=key %10.
    C Code:
    1. int hashfunc(int key)
    2. {
    3. return(key% 10);
    4. }
    Phép toán initialize
    Khởi động hàm băm.
    Gán biến toàn cục N=0.
    C Code:
    1. void initialize()
    2. {
    3. int i;
    4. for(i=0; i<M;i++)  hashtable[i].key = NULLKEY;
    5. N=0; //so nut hien co khoi dong bang 0
    6. }
    Phép toán empty:
    Kiểm tra bảng băm có rỗng không
    C Code:
    1. int empty()
    2. {
    3. return(N ==0 ?TRUE :FALSE);
    4. }
    Phép toán full:
    Kiểm tra bảng băm đã đầy chưa .
    C Code:
    1. int full()
    2. {
    3. return(N = = M-1 ?TRUE :FALSE);
    4. }
    Lưu ý bảng băm đầy khi N=M-1 chúng ta nên chừa ít nhất một phần tử trong trên bảng băm!

    Phép toán search:
    Tìm phần tử có khóa k trên bảng băm,nếu không tìm thấy hàm này trả về trị M, nếu tìm thấy hàm này trả về địa chỉ tìm thấy.
    C Code:
    1. int search(int k)
    2. {
    3. int i, d;
    4. i = hashfuns(k);
    5. d = 1;
    6. while(hashtable[i].key!=k&&hashtable[i].key !=NULLKEY)
    7. {
    8. //Bam lai (theo phuong phap bac hai)
    9. i = (i+d) % M;
    10. d = d*2;
    11. }
    12. hashtable[i].key =k;
    13. N = N+1;
    14. return(i);
    15. }
    Bảng băm với phương pháp băm kép (Double hashing Method)
    (Tham khảo Giáo trình cấu trúc dữ liệu _ Trần Hạnh Nhi-Dương Anh Đức)



    Tóm tắt Từ khoá

    • Bảng băm (Hash Table) : là bảng cho phép thực hiện tìm kiếm các phần tử với thời gian O(1) thông qua một hàm tính địa chỉ gọi là hàm băm
    • Hàm băm (Hash Function) : là hàm chuyển đổi giá trị khoá thành địa chỉ hay chỉ mục trong bảng băm
    • Sự đụng độ (Collision) : xảy ra khi hàm băm 2 khoá khác nhau vào cùng 1 địa chỉ trên bảng băm
    • Dò tuyến tính (Linear Probing Method): là một phương pháp băm lại (Rehash), để chọn một địa chỉ kế tiếp trong bảng băm khi xảy ra đụng độ về địa chỉ, bằng cách cộng thêm một đơn vị
    • Dò bậc hai (Quadratic Probing Method) :là một phương pháp băm lại để chọn một địa chỉ kế tiếp trong bảng băm khi xảy ra đụng độ về địa chỉ bằng cách cộng thêm i2 đơn vị vào địa chỉ
    • Phương pháp băm kép (Double hashing Method): là một phương pháp băm lại dùng cùng lúc hai hàm băm

  6. #6
    Ngày gia nhập
    10 2012
    Bài viết
    1

    Mặc định Lý thuyết tìm kiếm | Bảng băm ( hash table )

    không có phương pháp băm kép hả bạn ..... đang học mà viết cái Remove trong băm kép cứ lỗi hoài .....

Các đề tài tương tự

  1. Lý thuyết tìm kiếm - Tìm kiếm và so khớp chuỗi - Lập trình C
    Gửi bởi neverland87 trong diễn đàn Thủ thuật, Tutorials CTDL & Giải thuật
    Trả lời: 6
    Bài viết cuối: 12-06-2013, 06:14 PM
  2. Cách tạo code Hash table trong C#
    Gửi bởi thegioi911 trong diễn đàn Thắc mắc lập trình C#
    Trả lời: 19
    Bài viết cuối: 17-10-2011, 10:10 AM
  3. Hash function băm 1 chuỗi ra tọa độ địa lý
    Gửi bởi SadBoy1989 trong diễn đàn Thắc mắc lập trình Visual C++
    Trả lời: 0
    Bài viết cuối: 11-02-2011, 05:30 PM
  4. Về Hash Table(Bảng Băm)
    Gửi bởi x_tiger91 trong diễn đàn Thắc mắc lập trình C/C++/C++0x
    Trả lời: 1
    Bài viết cuối: 09-06-2010, 05:12 PM
  5. Lập trình tìm kiếm | Tìm kiếm với mảng băm (hashtable): ý tưởng & cài đặt
    Gửi bởi sonhn trong diễn đàn Thủ thuật, Tutorials CTDL & Giải thuật
    Trả lời: 10
    Bài viết cuối: 28-05-2007, 06:05 PM

Quyền hạn của bạn

  • Bạn không thể gửi đề tài mới
  • Bạn không thể gửi bài trả lời
  • Bạn không thể gửi các đính kèm
  • Bạn không thể chỉnh sửa bài viết của bạn