Tổng quan về giáo trình

Tài liệu học tập "Chapter 9: Hash" (Bảng băm) là bài giảng chuyên đề thuộc học phần Cấu trúc dữ liệu và Giải thuật (Data Structures and Algorithms), được biên soạn bởi hai giảng viên Lương Thế Nhân và Trần Giang Sơn thuộc Khoa Khoa học và Kỹ thuật Máy tính, Trường Đại học Bách Khoa – Đại học Quốc gia TP.HCM (Faculty of Computer Science and Engineering, University of Technology, VNU-HCM). Trong chương trình đào tạo kỹ sư và cử nhân ngành Công nghệ Thông tin và Khoa học Máy tính, học phần Cấu trúc dữ liệu và Giải thuật giữ vai trò kiến thức cơ sở ngành bắt buộc, làm nền tảng cho việc thiết kế giải thuật và tối ưu hóa hệ thống phần mềm.

Mục tiêu học tập của chương học được xác định cụ thể thông qua hệ thống chuẩn đầu ra (Learning Outcomes):

  • L.1: Trình bày và mô tả các khái niệm cơ bản gồm bảng băm (hashing table), khóa (key), xung đột (collision) và các phương pháp giải quyết xung đột (collision resolution).
  • L.2: Phân tích giải thuật và sử dụng ký pháp Big-O để đặc trưng hóa độ phức tạp tính toán của các giải thuật được xây dựng từ các cấu trúc điều khiển: tuần tự (sequence), rẽ nhánh (branching) và lặp (iteration - không xét đệ quy).
  • L.3: Mô tả các hàm băm và các phương pháp xử lý xung đột bằng mã giả (pseudocode), đồng thời cung cấp ví dụ minh họa từng bước thực thi thuật toán.
  • L.4: Cài đặt cấu trúc dữ liệu bảng băm hoàn chỉnh bằng ngôn ngữ lập trình C/C++.
  • L.5: Phân tích độ phức tạp và xây dựng chương trình thực nghiệm (experiment program) để đánh giá hiệu năng của các phương pháp bảng băm.

Nội dung bài giảng được cấu trúc theo phương pháp sư phạm tiếp cận từ bài toán thực tế: phân tích giới hạn của các cấu trúc tìm kiếm tuyến tính và nhị phân, thiết lập nhu cầu về cấu trúc dữ liệu đạt thời gian truy xuất $O(1)$, từ đó đi sâu vào cơ chế toán học của các hàm băm và kỹ thuật giải quyết xung đột bộ nhớ.


Nội dung kiến thức cốt lõi

Các chương/chủ đề chính

Nội dung bài giảng Chương 9 được chia thành 3 phần chính với tính logic kế thừa chặt chẽ:

  1. Khái niệm cơ bản (Basic Concepts):

    • Đặt vấn đề thông qua phân tích độ phức tạp thời gian: Tìm kiếm tuần tự (Sequential search) có chi phí trung bình và xấu nhất lần lượt là $O(n/2)$ và $O(n)$; Tìm kiếm nhị phân (Binary search) đạt $O(\log n)$. Cả hai phương pháp đều đòi hỏi nhiều phép so sánh khóa trước khi định vị được dữ liệu.
    • Bảng so sánh số phép so sánh tìm kiếm theo kích thước dữ liệu ($N$):
      • $N = 16$: Nhị phân = 4, Tuần tự (TB) = 8, Tuần tự (Xấu nhất) = 16.
      • $N = 256$: Nhị phân = 8, Tuần tự (TB) = 128, Tuần tự (Xấu nhất) = 256.
      • $N = 10,000$: Nhị phân = 14, Tuần tự (TB) = 5,000, Tuần tự (Xấu nhất) = 10,000.
      • $N = 1,000,000$: Nhị phân = 20, Tuần tự (TB) = 500,000, Tuần tự (Xấu nhất) = 1,000,000.
    • Định nghĩa mô hình bảng băm đạt độ phức tạp tìm kiếm lý tưởng $O(1)$ thông qua cơ chế ánh xạ địa chỉ trực tiếp từ khóa.
    • Các thuật ngữ nền tảng:
      • Home address: Địa chỉ được sinh ra bởi hàm băm.
      • Prime area: Vùng nhớ chứa tất cả các địa chỉ gốc.
      • Synonyms: Tập hợp các khóa khác nhau nhưng được băm ra cùng một địa chỉ.
      • Collision: Hiện tượng vị trí lưu trữ dữ liệu cần chèn đã bị chiếm giữ bởi một phần tử đồng nghĩa (synonym).
      • Ideal hashing: Trạng thái băm lý tưởng không xảy ra xung đột vị trí và không gian địa chỉ được tối ưu thu gọn (compact address space).
  2. Các phương pháp xây dựng hàm băm (Hash Functions): Bài giảng phân loại và cung cấp giải thuật chi tiết cho 7 phương pháp băm:

    • Direct Hashing: Địa chỉ chính là giá trị của khóa, $hash(Key) = Key$. Phương pháp này không xảy ra xung đột nhưng không gian địa chỉ phải lớn bằng toàn bộ không gian khóa.
    • Modulo Division: Tính địa chỉ theo công thức $Address = Key \pmod{listSize}$. Xung đột giảm thiểu khi $listSize$ là một số nguyên tố (prime number). Ví dụ: Quản lý 1.000.000 nhân viên trong không gian lưu trữ 300 phần tử, chọn kích thước nguyên tố $listSize = 307$, khóa $121267 \to 121267 \pmod{307} = 2$.
    • Digit Extraction: Trích xuất các chữ số ở vị trí xác định trong khóa. Ví dụ: Khóa 6 chữ số trích vị trí 1, 3, 4: $379452 \to 394$, $121267 \to 112$, $045128 \to 051$.
    • Mid-square: Bình phương khóa rồi lấy các chữ số ở giữa, $Address = \text{middle digits of } Key^2$. Ví dụ: $9452^2 = 89340304 \to 3403$. Biến thể thu gọn khóa khi $Key^2$ quá lớn: $379^2 = 143641 \to 364$, $121^2 = 014641 \to 464$, $045^2 = 002025 \to 202$.
    • Folding: Chia khóa thành các phần bằng kích thước địa chỉ:
      • Fold shift: $Key = 123|456|789 \to 123 + 456 + 789 = 1368 \to 368$.
      • Fold boundary: Đảo ngược các phần ở biên: $321 + 456 + 987 = 1764 \to 764$.
    • Rotation: Xoay vòng ký tự áp dụng cho tập khóa chỉ khác nhau ký tự cuối nhằm phân tán đều dữ liệu, thường kết hợp với Fold shift (ví dụ xoay $600101 \to 160010$, gấp lại thành 26 thay vì 62).
    • Pseudo-random: Sử dụng hàm giả ngẫu nhiên đồng dư tuyến tính $Address = ((a \times Key + c) \pmod{listSize})$, với $a$ và $c$ là các số nguyên tố. Ví dụ: $Key = 121267, a = 17, c = 7, listSize = 307 \to ((17 \times 121267 + 7) \pmod{307}) = 2061546 \pmod{307} = 41$.
  3. Phương pháp xử lý xung đột (Collision Resolution):

    • Nguyên tắc hệ số tải (Load Factor): $\alpha = (k / n) \times 100$, trong đó $n$ là kích thước danh sách, $k$ là số phần tử đã lưu. Quy tắc thực nghiệm khuyến nghị: Bảng băm không nên để đầy quá 75% ($\alpha \le 75%$).
    • Hiện tượng gom cụm (Clustering):
      • Primary clustering: Dữ liệu bị dồn cục xung quanh địa chỉ gốc (home address).
      • Secondary clustering: Dữ liệu bị gom nhóm dọc theo đường dẫn thăm dò xung đột (collision path).
    • Các nhóm kỹ thuật xử lý xung đột:
      • Địa chỉ mở (Open Addressing): Định vị ô nhớ trống tiếp theo thông qua hàm thăm dò $h_p: U \times {0, 1, \dots, m-1} \to {0, 1, \dots, m-1}$.
        • Linear Probing: Thăm dò tuyến tính $h_p(k, i) = (h(k) + i) \pmod m$. Ưu điểm: Đơn giản, dữ liệu nằm gần địa chỉ gốc (tối ưu khi lưu trữ trên đĩa). Nhược điểm: Tạo ra hiện tượng gom cụm sơ cấp (primary clustering).
        • Quadratic Probing: Thăm dò bậc hai $h_p(k, i) = (h(k) + i^2) \pmod m$. Ưu điểm: Khắc phục gom cụm sơ cấp tốt hơn tuyến tính. Nhược điểm: Tốn chi phí tính toán bình phương và gây ra gom cụm thứ cấp (secondary clustering) do các khóa trùng $h(k)$ sẽ có cùng chuỗi thăm dò.
        • Double HashingKey Offset.
      • Giải quyết bằng danh sách liên kết (Linked List Resolution / Chaining).
      • Băm theo thùng chứa (Bucket Hashing).

Kiến thức nền tảng được xây dựng

Tài liệu xây dựng hệ thống lý thuyết chuẩn tắc:

  • Nguyên lý ánh xạ toán học: Phân biệt ánh xạ một-một ($1-1$ mapping trong Direct Hashing) và ánh xạ nhiều-một (many-to-one mapping trong Modulo Division và các hàm băm khác), từ đó thiết lập tính tất yếu của các cơ chế giải quyết xung đột.
  • Lý thuyết số trong phân bố khóa: Ứng dụng số nguyên tố (prime numbers) trong việc chọn kích thước bảng băm $listSize$ và các hằng số nhân $a, c$ để cực đại hóa chu kỳ phân tán, giảm thiểu chu kỳ lặp dư số.
  • Mô hình giải thuật chuẩn tắc:
    • Mã giả thao tác chèn (hashInsert): Sử dụng vòng lặp kiểm tra $T[j] = \text{nil}$ với $j = h_p(k, i)$, trả về địa chỉ chèn hoặc báo lỗi tràn bảng khi $i \ge m$.
    • Mã giả thao tác tìm kiếm (hashSearch): Duyệt qua hàm thăm dò $h_p(k, i)$, dừng khi tìm thấy $T[j] = k$ hoặc gặp ô trống $\text{nil}$.

Kỹ năng phát triển

  • Kỹ năng kỹ thuật: Lập trình cài đặt bảng băm, các hàm băm và giải thuật giải quyết xung đột bằng ngôn ngữ C/C++; kiểm soát bộ nhớ động và con trỏ.
  • Kỹ năng phân tích: Phân tích độ phức tạp thời gian của giải thuật sử dụng ký pháp Big-O; tính toán hệ số tải $\alpha$; xác định các dạng gom cụm dữ liệu trong bộ nhớ.
  • Năng lực thực nghiệm: Thiết kế và triển khai chương trình đo đạc thực nghiệm trên máy tính để so sánh số bước thăm dò thực tế giữa các giải thuật băm và thăm dò khác nhau.

Phương pháp giảng dạy và học tập

Phương pháp tiếp cận sư phạm

Giáo trình sử dụng phương pháp đối chiếu định lượng để tạo động lực nhận thức:

  1. Đặt sinh viên vào bài toán tìm kiếm trên tập dữ liệu kích thước lớn ($N = 10^6$), so sánh trực quan $20$ phép toán của tìm kiếm nhị phân với hàng trăm nghìn phép so sánh của tìm kiếm tuyến tính.
  2. Đặt câu hỏi mở: "Is there a search algorithm whose complexity is O(1)?" để dẫn dắt tự nhiên vào bản chất của giải thuật băm.
  3. Chuyển đổi từ mô hình toán học giải tích sang mã giả (pseudocode), sau đó tiến tới hiện thực hóa trên ngôn ngữ lập trình cụ thể (C/C++).

Bài tập và bài toán tình huống

Tài liệu cung cấp các bài toán tính toán cụ thể:

  • Bài toán Modulo: Xử lý hệ thống định danh 1.000.000 nhân viên trong mảng 307 phần tử với khóa $121267$.
  • Bài toán Mid-square: Thao tác tính toán trên số nguyên 4 chữ số $9452 \to 9452^2 = 89340304$, lấy 4 chữ số giữa để xác định địa chỉ 3403.
  • Bài toán Folding: So sánh sự khác biệt giữa phép gấp trượt (fold shift) và phép gấp biên (fold boundary) trên cùng một chuỗi khóa $123|456|789$.
  • Bài toán Pseudo-random: Thực hiện chuỗi tính toán $((17 \times 121267 + 7) \pmod{307})$.

Phương pháp đánh giá

  • Đánh giá lý thuyết: Khả năng giải thích bản chất toán học của các hàm băm, phân biệt xung đột sơ cấp và thứ cấp.
  • Đánh giá giải thuật: Viết mã giả và tính toán chỉ số Big-O cho các hàm thao tác bảng băm.
  • Đánh giá thực hành: Đánh giá mã nguồn chương trình C/C++, kiểm thử tính đúng đắn của bảng băm khi hệ số tải vượt ngưỡng khuyến nghị $75%$.

Điểm nổi bật và tính cập nhật

  • Tính hệ thống và bao quát: Bài giảng tổng hợp đầy đủ 7 phương pháp băm dữ liệu kinh điển cùng 3 nhóm giải pháp xử lý xung đột chính của cấu trúc dữ liệu.
  • Phân tích nhược điểm kỹ thuật rõ ràng: Không chỉ nêu khái niệm, tài liệu chỉ rõ hạn chế cơ chế của từng giải thuật:
    • Direct Hashing: Lãng phí không gian bộ nhớ bằng kích thước không gian khóa.
    • Mid-square: Tràn số khi $Key^2$ vượt giới hạn biểu diễn của kiểu dữ liệu nguyên (được khắc phục bằng cách lấy một phần khóa).
    • Linear Probing: Hiện tượng Primary clustering làm suy giảm hiệu năng tìm kiếm cục bộ.
    • Quadratic Probing: Chi phí tính lũy thừa bậc hai và hiện tượng Secondary clustering.
  • Gắn liền ứng dụng hệ thống: Tài liệu nhấn mạnh đặc thù kỹ thuật của Linear Probing khi áp dụng cho địa chỉ đĩa từ (disk addresses), nơi việc các phần tử nằm liền kề nhau giúp giảm độ trễ cơ học khi đọc/ghi dữ liệu.

Đối tượng sử dụng giáo trình

  • Sinh viên đại học: Sinh viên năm thứ 2 hoặc năm thứ 3 chuyên ngành Khoa học Máy tính, Kỹ thuật Máy tính, Công nghệ Thông tin, Hệ thống Thông tin.
  • Điều kiện tiên quyết (Prerequisites):
    • Nắm vững kiến thức lập trình cơ bản và nâng cao với C/C++ (đặc biệt là con trỏ, cấp phát bộ nhớ động, mảng và cấu trúc dữ liệu struct).
    • Hiểu biết về toán rời rạc cơ bản: Số học đồng dư (modular arithmetic), số nguyên tố.
    • Đã học các kỹ thuật phân tích độ phức tạp thời gian giải thuật bằng ký pháp Big-O ($O(1), O(\log n), O(n)$).
  • Giảng viên: Sử dụng làm đề cương slide bài giảng chuẩn, khung tài liệu hướng dẫn bài tập lớn và bài thực hành phòng lab.

Câu hỏi thường gặp

1. Giáo trình này phù hợp với ai?

Tài liệu được thiết kế trực tiếp cho sinh viên đại học khối ngành Công nghệ Thông tin - Kỹ thuật Máy tính đang theo học học phần Cấu trúc dữ liệu và Giải thuật, cũng như kỹ sư phần mềm cần củng cố kiến thức nền tảng về bảng băm và tối ưu hóa thời gian truy xuất dữ liệu.

2. Cần kiến thức nền nào trước khi tiếp cận chương học này?

Người học cần có nền tảng về ngôn ngữ lập trình C hoặc C++, hiểu nguyên lý hoạt động của mảng và danh sách liên kết, có kiến thức về phép toán chia lấy dư (modulo) và phương pháp đánh giá độ phức tạp tính toán bằng ký pháp Big-O.

3. Điểm khác biệt giữa Linear Probing và Quadratic Probing là gì?

Theo tài liệu, Linear Probing tăng bước thăm dò tuyến tính $h_p(k, i) = (h(k) + i) \pmod m$, dễ cài đặt nhưng sinh ra hiện tượng gom cụm sơ cấp (primary clustering). Quadratic Probing tăng bước thăm dò theo bình phương số lần thử $h_p(k, i) = (h(k) + i^2) \pmod m$, giúp phân tán dữ liệu tốt hơn nhưng tốn chi phí tính toán bình phương và sinh ra gom cụm thứ cấp (secondary clustering).

4. Tại sao kích thước bảng băm nên là một số nguyên tố?

Trong phương pháp băm Modulo Division ($Address = Key \pmod{listSize}$), việc chọn $listSize$ là số nguyên tố giúp giảm thiểu hiện tượng trùng lặp số dư đối với các khóa có tính tuần hoàn hoặc chia sẻ ước số chung, qua đó giảm tỷ lệ xảy ra xung đột (fewer collisions).

5. Giới hạn hệ số tải an toàn cho bảng băm là bao nhiêu?

Theo nguyên tắc kinh nghiệm được nêu trong tài liệu (slide 9.30), hệ số tải của bảng băm $\alpha = (k / n) \times 100$ không nên vượt quá $75%$ dung lượng bảng để hạn chế việc gom cụm và tăng số bước thăm dò.


Kết luận

Bài giảng "Chapter 9: Hash" của tác giả Lương Thế Nhân và Trần Giang Sơn cung cấp khung kiến thức chuẩn mực và toàn diện về bảng băm trong cấu trúc dữ liệu và giải thuật. Nội dung kết hợp giữa phân tích độ phức tạp toán học, đặc tả giải thuật bằng mã giả và hướng dẫn cài đặt thực nghiệm trên C/C++. Lộ trình học tập khuyến nghị cho người học là: nắm vững định nghĩa về địa chỉ gốc và xung đột $\to$ thực hành tính toán thủ công các hàm băm trên số liệu mẫu $\to$ viết mã giả thao tác chèn/tìm kiếm $\to$ cài đặt mã nguồn C/C++ và chạy chương trình đo lường thực nghiệm số phép thăm dò theo các mức hệ số tải khác nhau.