Đặc tả thuật toán môn thiết kế cơ sở dữ liệu

Cơ sở dữ liệu quan hệ được xây dựng theo lý thuy ết do E.F.Codd giới thiệu năm 1970. Mô hình quan hệ có nhiều ưu điểm hơn hẳn các mô hình trước nó và từ năm 1980 đã trở thành mô hình được dùng rộng rãi để phát triển hệ quản trị CSDL. Cùng với sự phát triển của mô hình dữ liệu quan hệ, có nhiều vấn đề lý thuy ết và thực nghiệm nảy sinh và được giải quy ết . Khi thiết k ế CSDL quan hệ ta thường đứng trước vấn đề lựa chọn giữa các lược đồ quan hệ: lược đồ nào tốt hơn? Tại sao?

pdf26 trang | Chia sẻ: lvbuiluyen | Lượt xem: 2004 | Lượt tải: 3download
Bạn đang xem trước 20 trang tài liệu Đặc tả thuật toán môn thiết kế cơ sở dữ liệu, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
1 ĐẠI HỌC QUỐC GIA THÀNH PHỐ HỒ CHÍ MINH TRƯỜNG ĐẠI HỌC CÔNG NGHỆ THÔNG TIN KHOA HỆ THỐNG THÔNG TIN ĐẶC TẢ THUẬT TOÁN MÔN THIẾT KẾ CƠ SỞ DỮ LIỆU Sinh viên thực hiện :  Trần Hưng Nghiệp – 07520245  Nguyễn Thành Phương – 07520285  Nguyễn Ngọc Linh – 07520194 GIÁO VIÊN HƯỚNG DẪN: Phan Nguyễn Thụy An Thành phố Hồ Chí Minh, tháng 1 năm 20 2 CHƯƠNG 1: TỔNG QUAN 1. Đặt vấn đề: Cơ sở dữ liệu quan hệ được xây dựng theo lý thuyết do E.F.Codd giới thiệu năm 1970. Mô hình quan hệ có nhiều ưu điểm hơn hẳn các mô hình trước nó và từ năm 1980 đã trở thành mô hình được dùng rộng rãi để phát triển hệ quản trị CSDL. Cùng với sự phát triển của mô hình dữ liệu quan hệ, có nhiều vấn đề lý thuyết và thực nghiệm nảy sinh và được giải quyết . Khi thiết kế CSDL quan hệ ta thường đứng trước vấn đề lựa chọn giữa các lược đồ quan hệ: lược đồ nào tốt hơn? Tại sao? … Có thể nói tổng quát một lược đồ quan hệ có cấu trúc tốt là lược đồ không chứa đựng các vấn đề liệt kê sau đây: a. Dư thừa dữ liệu Là sự trùng lặp thông tin trong CSDL. Ví dụ: Xét lược đồ quan hệ NHACC(Ten_NCC, Hang, DonGia, Diachi_NCC). Nếu một nhà cung cấp cung cấp nhiều mặt hàng thì địa chỉ nhà cung cấp phải lặp lại nhiều lần  kéo theo dư thừa dữ liệu. Ngoài việc gây lãng phí dung lượng lưu trữ, sự dư thừa dữ liệu có thể gây ra những hậu quả nghiêm trọng đối với dữ liệu khi người dùng cập nhật dữ liệu làm cho dữ liệu không tương thích, thiếu nhất quán. Ví dụ: Xét lại lược đồ NHACC trên. Ta có thể sửa địa chỉ một nhà cung cấp tại một bộ nào đó mà không sửa ở một bộ khác gây ra địa chỉ không nhất quán của cùng một nhà cung cấp. b. Dị thường do thêm dữ liệu Không thể chèn bộ mới vào quan hệ nếu không có đầy đủ dữ liệu. Ví dụ: Ta không thể ghi nhận địa chỉ một nhà cung cấp nếu nhà cung cấp đó không cung cấp mặt hàng nào cả vì Ten_NCC, Hang tạo thành một khoá cho quan hệ. c. Dị thường do xóa dữ liệu 3 Ngược lại với vấn đề c, khi ta xoá hết các mặt hàng do một hãng cung cấp, ta không thể theo dõi được địa chỉ của hãng đó. Trong ví dụ trên, vấn đề này sẽ không còn nữa khi ta thay quan hệ NHACC bằng hai quan hệ: NCC_ĐC(TÊN_NCC, ĐC_NCC) NCC_HG(TÊN_NCC, TÊN_HG, GIA) Cách giải quyết các vấn đề trên khi thiết kế lược đồ quan hệ là xây dựng lược đồ đạt các dạng chuẩn. 2. Cơ sở kiến thức: a. Phụ thuộc hàm: Phụ thuộc hàm (functional dependancy) là một công cụ dùng để biểu diễn một cách hình thức các ràng buộc toàn vẹn. Phương pháp biểu diễn này có rất nhiều ưu điểm, và đây là một công cực kỳ quan trọng, gắn chặt với lý thuyết thiết kế cơ sở dữ liệu. Phụ thuộc hàm có ứng dụng trong việc giải quyết các bài toán như: tìm khoá, tìm phủ tối thiểu, xác định dạng chuẩn… Định Nghĩa Phụ Thuộc Hàm: Cho R(A1,…,An) là một sơ đồ quan hệ với tập thuộc tính U={A1,…,An}. X và Y là tập con của U. Xét một quan hệ cụ thể r nao đó. Ta nói X  Y (đọc là: X xác định hàm Y hoặc Y phụ thuộc hàm vào X) nếu với mỗi cặp bộ u, v của r thỏa: u[X] = v[X]  u[Y] = v[Y] Để chứng minh và suy ra các phụ thuộc hàm khác từ các phụ thuộc hàm đã có ta dùng hệ tiên đề Armstrong: Gọi R(U) là lược đồ quan hệ với U = {A1,…,An} là tập các thuộc tính. X, Y, Z, W  U. Hệ tiên đề Armstrong bao gồm: F1) Tính phản xạ: Y  X  X  Y 4 F2) Tính tăng trưởng: X  Y  XZ  YZ F3) Tính bắc cầu: X  Y, Y  Z  X  Z b. Bao đóng: Bao đóng (closure) của tập phụ thuộc hàm F (ký hiệu là F+) là tập hợp tất cả các phụ thuộc hàm có thể suy ra từ F dựa vào các tiên đề Armstrong. Tức nó phải thoả hai tính chất sau: i) F+  F ii) Khi áp dụng các hệ tiên đề Armstrong cho F+ ta không thu được phụ thuộc hàm nào nằm ngoài F+. Bao Đóng Của Tập Thuộc Tính : Cho tập phụ thuộc hàm F trên tập thuộc tính U và X  U. Bao đóng của tập thuộc tính X (đối với F), ký hiệu X+, là tập sau: X+ = {A | X  A  F+} c. Bài toán thành viên: Qua phần trên ta nhận thấy X+ được định nghĩa thông qua F+. Vấn đề nảy sinh khi nghiên cứu lý thuyết CSDL là: Cho trước tập các phụ thuộc hàm F và một phụ thuộc hàm f, bài toán kiểm tra có hay không f ∈ F+ gọi là bài toán thành viên. d. Siêu khóa, khóa: Cho quan hệ R(U, F), với U là tập thuộc tính, F là tập phụ thuộc hàm. Cho K ⊆ U. Định nghĩa Siêu Khoá Của Quan Hệ : K là một siêu khoá của R nếu thoả điều kiện sau: K xác định hàm mọi thuộc tính trong U. Tức là K+ = U. Định nghĩa Khoá Của Quan Hệ : 5 K là một khoá của R nếu thỏa: K là siêu khóa và không có siêu khóa nào nhỏ hơn K. Tức là K+ = U và H⊂K ⇒ H+ ≠ U. Một lược đồ quan hệ có thể có nhiều siêu khoá, nhiều khoá. e. Phủ tối thiểu: Tập phụ thuộc hàm tối thiểu là tập phụ thuộc hàm thoả mãn các điều kiện sau: 1) Vế phải của mỗi phụ thuộc hàm trong F chỉ có 1 thuộc tính. 2) Mọi phụ thuộc hàm X  A  F đều không dư thừa, tức là tập phụ thuộc hàm có từ F bằng sự loại bỏ phụ thuộc hàm X  A: F \ {X  A} không tương đương với F. 3) Với mỗi phụ thuộc hàm X  A  F, mọi thuộc tính B  X đều không dư thừa, tức là tập phụ thuộc hàm có từ F bằng việc thay phụ thuộc hàm X  A bởi phụ thuộc hàm (X \{B})  A : (F \ {X  A})  {X \ {B})  A} không tương đương với F. Tập phụ thuộc hàm tương đương của F: Tập phụ thuộc hàm G được gọi là tương đương với F nếu và chỉ nếu F+ = G+ Ký hiệu: F ≡ G Phủ tối thiểu của F: Là tập phụ thuộc hàm tối thiểu và tương đương với F Ký hiệu : PTT(F) f. Các dạng chuẩn: Như đã nói ở trên, một lược đồ quan hệ có thể bị dư thừa dữ liệu, dị thường do thêm, dị thường do xóa. Những vấn đề trên đã được giải quyết qua việc xây dựng các dạng chuẩn. Xét lược đồ quan hệ R(U, F), với U là tập thuộc tính, F là tập phụ thuộc hàm. 6 i) Dạng chuẩn 1: R được xem là đạt dạng chuẩn 1 nếu mọi thuộc tính của R đều khác rỗng, phụ thuộc hàm vào khoá và có miền trị nguyên tố (tức là không đa hợp và đa trị). ii) Dạng chuẩn 2: R được xem là đạt dạng chuẩn 2 nếu nó đạt dạng chuẩn 1 và mọi thuộc tính không khóa phải phụ thuộc đầy đủ vào khóa. iii) Dạng chuẩn 3: R được xem là đạt dạng chuẩn 3 nếu nó đạt dạng chuẩn 2 và mọi thuộc tính không khóa đều không phụ thuộc bắc cầu vào khóa. Một cách định nghĩa khác : R được xem là đạt dạng chuẩn 3 nếu mọi phụ thuộc hàm không hiển nhiên trong F đều có vế trái chứa khóa hay vế phải nằm trong khóa iv) Dạng chuẩn B – C : R được xem là đạt dạng chuẩn B – C nếu mọi phụ thuộc hàm không hiển nhiên trong F đều có vế trái chứa khóa. 3. Yêu cầu cho đề tài:  Đề tài phải trình bày rõ ràng các thuật toán sau và các thuật toán bổ trợ: o Thuật toán tìm Bao đóng o Thuật toán kiểm tra Phụ thuộc hàm thành viên o Thuật toán tìm Khóa o Thuật toán tìm Phủ tối thiểu o Thuật toán xác định Dạng chuẩn  Cài đặt thử nghiệm các thuật toán trên trong phần mềm có giao diện đồ họa, nhập liệu trực tiếp hay từ file dữ liệu nhập. 7 CHƯƠNG 2: CHI TIẾT CÁC THUẬT TOÁN 1. Thuật toán tìm Bao đóng cho tập thuộc tính: Cho lược đồ quan hệ R(U, F), tập thuộc tính U, tập phụ thuộc hàm F. Tìm X+F? a. Ý tưởng: - Bao đóng của X ít nhất có X. - Duyệt qua tất cả các phụ thuộc hàm, nếu vế trái nằm trong Bao đóng thì thêm vế phải vào Bao đóng. - Lặp lại đến khi đi hết một lượt mà không có thêm thuộc tính nào được thêm vào Bao đóng. b. Mô hình hóa:  Input: Tập thuộc tính cần tìm bao đóng X, Tập phụ thuộc hàm F.  Output: Bao đóng X+F. 8 TimBaoDong(X, F) { TapCu = null TapMoi = X While (TapCu TapMoi) TapCu = TapMoi for each (pth P->Q) in F If P  TapMoi Then TapMoi = TapMoi  Q End If Next (pth P->Q) End While Return TapMoi } c. Độ phức tạp, nhận xét, cải tiến: Thuật toán trên có độ phức tạp tính toán O(n2) với n là số thuộc tính của lược đồ quan hệ R. Thuật toán có thể cải tiến bằng cách: Sau khi thêm Q vào TapMoi, ta loại bỏ pth P->Q ra khỏi F. Vì ta đã thêm Q rồi nên không cần xét thêm nữa. Ta có thể xây dựng thuật toán với độ phức tạp tuyến tính, sử dụng LIST. 2. Thuật toán kiểm tra phụ thuộc hàm thành viên: Cho lược đồ quan hệ R(U, F), tập thuộc tính U, tập phụ thuộc hàm F. Cho phụ thuộc hàm f: X->Y. Kiểm tra xem f có thuộc F+ không? a. Ý tưởng: - X->Y  F+  X+F  Y b. Mô hình hóa:  Input: Phụ thuộc hàm cần kiểm tra f: X→Y, Tập phụ thuộc hàm F.  Output: true nếu f là thành viên của F+, false nếu ngược lại. KiemTraPTHThanhVien(X, Y, F) { X+F = TimBaoDong(X, F) 9 if Y  X+F then return true else return false } c. Độ phức tạp, nhận xét, cải tiến: Thuật toán trên có độ phức tạp tính toán O(n2) với n là số thuộc tính của lược đồ quan hệ R. Đó cũng là độ phức tạp của thuật toán tìm Bao đóng của tập thuộc tính, là cốt lõi của thuật toán này. 3. Thuật toán tìm khóa: Cho lược đồ quan hệ R(U, F), tập thuộc tính U, tập phụ thuộc hàm F. Tìm tất cả các khóa của R? a. Ý tưởng: (Tìm khóa Vét cạn) - Tìm tất cả các siêu khóa : o Liệt kê tất cả các tập con của U o Tìm bao đóng của các tập con đó o Nếu Bao đóng = U thì tập con đó là siêu khóa. - So sánh các siêu khóa, loại bỏ cái lớn hơn đi được các khóa. b. Mô hình hóa:  Input: Tập thuộc tính U, Tập phụ thuộc hàm F.  Output: Tập các khóa K. TimKhoaVetCan(U,F) { Dim CacTapCon, CacSieuKhoa CacTapCon = TimCacTapCon(U) for each TapCon in CacTapCon { if TimBaoDong(TapCon, F) = U then 10 CacSieuKhoa = CacSieuKhoa  {TapCon} end if } 'loại bỏ các siêu khóa không nhỏ hơn for each SieuKhoa1 in CacSieuKhoa for each SieuKhoa2 in CacSieuKhoa { if SieuKhoa2  SieuKhoa1 then CacSieuKhoa = CacSieuKhoa \ SieuKhoa1 break; end if } Return CacSieuKhoa ' Tập các khóa cuối cùng sau khi đã bỏ các siêu khóa không nhỏ hơn đi } c. Độ phức tạp, nhận xét, cải tiến: Thuật toán trên có độ phức tạp tính toán O(2nn2) với n là số thuộc tính của lược đồ quan hệ R. Bảo đảm tìm được tất cả các Siêu khóa và các Khóa. Khi số thuộc tính trong U là lớn thì việc duyệt qua tất cả các tập con là không khả thi. Nên ta đưa ra thuật toán tìm khóa bằng đồ thị sau để giới hạn số tập con sẽ xét. Thuật toán này chỉ để tham khảo, chương trình của nhóm không sử dụng thuật toán này. d. Ý tưởng: (Tìm khóa bằng đồ thị) - Dựa trên biểu diễn đồ thị của R: Gốc là thuộc tính chỉ nằm bên vế trái, Cô lập là thuộc tính không ở trong phụ thuộc hàm nào, Trung gian là thuộc tính nằm ở cả hai vế, Lá là thuộc tính chỉ nằm bên vế phải. - Các thuộc tính ở gốc và cô lập chắc chắn nằm trong khóa. - Các thuộc tính trung gian có thể ở trong khóa hoặc không. - Các thuộc tính ở lá chắc chắn không ở trong khóa. e. Mô hình hóa: 11  Input: Tập thuộc tính U, Tập phụ thuộc hàm F.  Output: Tập các khóa K. TimKhoaDoThi(U, F) { for each (pth P->Q) in F { VT = VT  P VP = VP  Q } Goc = VT \ VP 'chi nam o ve trai TrungGian = VT \ (VT \ VP) 'Nam o ca hai ve CoLap = U \ VT \ VP SK = Goc  CoLap If TimBaoDong(SK, F) = U Then Return SK 'là khóa duy nhất Else Dim CacTapcon, CacSieuKhoa CacTapcon = TimCacTapCon(TrungGian) For Each TapCon In CacTapcon { SKK = SK  TapCon If TimBaoDong(SKK, F) = U Then CacSieuKhoa = CacSieuKhoa  {SKK} End If } 'loại bỏ các siêu khóa không nhỏ hơn for each SieuKhoa1 in CacSieuKhoa for each SieuKhoa2 in CacSieuKhoa { if SieuKhoa2  SieuKhoa1 then CacSieuKhoa = CacSieuKhoa \ SieuKhoa1 break; end if } Return CacSieuKhoa ' Tập các khóa cuối cùng sau khi đã bỏ các siêu khóa không nhỏ hơn đi } f. Độ phức tạp, nhận xét, cải tiến: Thuật toán trên có độ phức tạp tính toán tối đa O(2nn2) với n là số thuộc tính của lược đồ quan hệ R. Nhưng thường đạt thấp hơn do giới hạn số tập con cần duyệt không phải 2n nữa. 12 Bảo đảm tìm được tất cả các Khóa. Nhưng không bảo đảm tìm được tất cả các siêu khóa. 4. Thuật toán tìm Phủ tối tiểu cho tập phụ thuộc hàm: Cho lược đồ quan hệ R(U, F), tập thuộc tính U, tập phụ thuộc hàm F. Tìm PTT(F)? d. Ý tưởng: - Tách vế phải ra thành các thuộc tính đơn. - Thay thế các phụ thuộc hàm không đầy đủ. - Loại bỏ các phụ thuộc hàm dư thừa. e. Mô hình hóa:  Input: tập phụ thuộc hàm F  Output: Phủ tối thiểu của F: PTT(F) TimPTT(F) { F = TachPTH(F) F = LoaiPTHDuThua(F) F = ThayThePTHKhongDayDu(F) Return F } '-------------------------------------------------------- TachPTH(F) { for each (pth P->Q) in F { CacPhanTu = TimTungPhanTu(Q) F = F \ (P->Q) For Each PhanTu in CacPhanTu F = F  (P->PhanTu) } } ThayThePTHKhongDayDu(F) { for each (pth P->Q) in F { 13 for each Pi in P1P2…Pk ->Q { if F=(F-{P1…Pi…Pk-> Q}){P1…Pi-1Pi+1 …Pk->Q}then P=P\Pi end if } } } '-------------------------------------------------------- LoaiPTHDuThua(F) { for each (pth f = P->Q) in F { P+(F\f) = TimBaoDong(P, (F \ f)) if P+(F\f)  Q then F = F \ f } } '-------------------------------------------------------- f. Độ phức tạp, nhận xét, cải tiến: Thuật toán trên chỉ cho ta 1 PTT(F), các phủ tối thiểu khác có được khi ta thay đổi thứ tự của các tập con khi thay thế các phụ thuộc hàm không đầy đủ. 5. Thuật toán xác định Dạng Chuẩn: Cho lược đồ quan hệ R(U, F), tập thuộc tính U, tập phụ thuộc hàm F. Xác định dạng chuẩn? a. Ý tưởng: - Tìm tất cả các khóa - Kiểm tra dạng chuẩn BC - Kiểm tra dạng chuẩn 3 - Kiểm tra dạng chuẩn 2 - Kiểm tra dạng chuẩn 1. b. Mô hình hóa: 14  Input: Tập thuộc tính U, Tập phụ thuộc hàm F, TatCaThuocTinhCoMienTriNguyenTo.  Output: o Không đạt dạng chuẩn nào return 0 o Đạt dạng chuẩn 1 return 1 o Đạt dạng chuẩn 2 return 2 o Đạt dạng chuẩn 3 return 3 o Đạt dạng chuẩn BC return 4 XacDinhDangChuan(U, F, TatCaThuocTinhThoaMienTriNguyenTo) { TapKhoa = TimKhoaDoThi(U, F) F’ = TachPTH(F) If DCBC(TapKhoa, F’) then Return 4 Else if DC3(TapKhoa, F’) then Return 3 Else if DC2(TapKhoa, F’) then Return 2 Else if TatCaThuocTinhCoMienTriNguyenTo then Return 1 Else Return 0 } '------------------------------------------------------- DCBC(TapKhoa, F’) { for each (fth P->Q) in F’ { if (Q  P) then Re = false for each K in TapKhoa { if (P  K) then Re = true Break; end if } If Re = false then Return false End If end if } 15 return true } '------------------------------------------------------- DC3(TapKhoa, F’) { for each (fth P->Q) in F’ { if (Q  P) then Re1 = false Re2 = false for each K in TapKhoa { if (P  K) then Re1 = true Break; end if } for each K in TapKhoa { if (Q  K) then Re2 = true Break; end if } If ((Re1 = false) AND (Re2 = false)) then Return false end if end if } return true } '------------------------------------------------------- DC2_New(TapKhoa, F’) 'F’ là F có vế phải 1 thuộc tính { for each (pth P->Q) in F' for each K in TapKhoa if (P  K) AND (P K) then return false end if return true } '------------------------------------------------------- DC2_Old(TapKhoa, F, U) { TTKK = U 16 for each K in TapKhoa TTKK = TTKK \ K for each KK in TTKK for each K in TapKhoa { TapCon = TimTapCon(K) TapCon = TapCon \ K for each TC in TapCon if (TC+F  KK) then return false end if } return true } c. Độ phức tạp, nhận xét, cải tiến: Thuật toán trên phụ thuộc nhiều vào các thuật toán thành phần của nó. Thông thường thì các lược đồ quan hệ ta xét đều có miền trị nguyên tố và đạt dạng chuẩn 1. 6. Các thuật toán hỗ trợ: Tìm các tập con a. Ý tưởng: Xây dựng lần lượt các tập con có số thuộc tính tăng dần để không phải sắp xếp. b. Mô hình hóa:  Input: Tập thuộc tính U  Output: Tất cả tập con của U 17 U gồm n phần tử TapCon gồm 2^n-1 phần tử TapCon = U For i = 0 to 2^n -1 For j = last(TapCon (i)) to n-1 TapCon.Add(TapCon (i) + U (j)) Next Next * ( last(AB) = vị trí của B trong U, last(AB)=1 , last(AC) =2) Debug mẫu a. A B C D b. AB AC AD BC BD CD c. ABC ABD ACD BCD d. ABCD CHƯƠNG 3: CÀI ĐẶT CÁC THUẬT TOÁN I. Cấu trúc dữ liệu List được dùng làm cấu trúc lưu trữ chính vì đây là cấu trúc động, sử dụng tối ưu cho bộ nhớ, và có các hàm cần thiết hỗ trợ như : Add, Addrange, index, RemoveAt … Tập thuộc tính U: Dim str_U As List(Of String) 18 Mục đích: Mỗi thuộc tính là 1 string riêng biệt, có thể có khoảng trắng ở giữa. Phụ thuộc hàm : Class F Class F Public Left As New List(Of String) 'Vế trái của PTH, gồm 1 danh sách các string Public Right As New List(Of String) 'Vế phải của PTH, gồm 1 danh sách các string Tập phụ thuộc hàm : Dim lst_F As List(Of F) Tập con (Tập hợp gồm nhiều tập thuộc tính): Dim lst_Tap_Con As List(Of List(Of String)) Tập khóa (Tập hợp gồm nhiều tập khóa) Dim lst_Khoa As List(Of List(Of String)) II. Các thuật toán a. Tìm bao đóng Public Function XPlusF(ByVal X As List(Of String), ByVal F As List(Of F)) As List(Of String) Dim str_old As New List(Of String) Dim str_kq As New List(Of String) Dim flag As Boolean Dim count As Integer = F.Count - 1 For i As Integer = 0 To X.Count - 1 str_kq.Add(X(i)) Next Do str_old.Clear() For i As Integer = 0 To str_kq.Count - 1 str_old.Add(str_kq(i)) Next For dem As Integer = 0 To count flag = True 19 For dem2 As Integer = 0 To F(dem).Left.Count - 1 If str_kq.Contains(F(dem).Left(dem2)) = False Then flag = False End If If flag = False Then Exit For End If Next If flag Then For dem2 = 0 To F(dem).Right.Count - 1 If str_kq.Contains(F(dem).Right(dem2)) = False Then str_kq.Add(F(dem).Right(dem2)) End If Next End If Next Loop Until str_old.Count = str_kq.Count Return str_kq End Function b. Tìm khóa Private Function Tim_Khoa(ByVal lst_U As List(Of String), ByVal lst_F As List(Of F)) As List(Of List(Of String)) Dim lst_Goc As New List(Of String) 'Các thuộc tính gốc (1) Dim lst_TG As New List(Of String) ' Các thuộc tính trung gian (3) Dim lst_R As New List(Of String) ' Các thuộc tính cô lập ( rời) (4) Dim lst_key As New List(Of String) ' Kết quả Dim lst_kq As New List(Of List(Of String)) Dim int_kt As Integer 'Thiết lập tập gốc, trung gian, rời rạc For i As Integer = 0 To lst_U.Count - 1 int_kt = Kiem_Tra_TT(lst_U(i), lst_F) If int_kt = 1 Then lst_Goc.Add(lst_U(i)) ElseIf int_kt = 2 Then lst_TG.Add(lst_U(i)) ElseIf int_kt = 4 Then lst_R.Add(lst_U(i)) End If Next 20 For i = 0 To lst_Goc.Count - 1 lst_key.Add(lst_Goc(i)) Next For i = 0 To lst_R.Count - 1 lst_key.Add(lst_R(i)) Next If lst_key.Count 0 Then lst_kq.Add(lst_key) End If If XPlusF(lst_key, lst_F).Count = lst_U.Count Then 'Kiểm tra xem tập Gốc giao Rời có phải là khóa duy nhất không Return lst_kq Else If lst_kq.Count > 0 Then lst_kq.RemoveAt(0) End If Dim lst_Tap_Con As New List(Of List(Of String)) lst_Tap_Con = Tim_tap_Con_New(lst_TG) Dim test As Integer For i = 0 To lst_Tap_Con.Count - 1 test = 1 Dim lst_key_tmp As New List(Of String) lst_key_tmp.AddRange(lst_key) lst_key_tmp.AddRange(lst_Tap_Con(i)) 'Add lần lượt các tập con vào khóa If XPlusF(lst_key_tmp, lst_F).Count = lst_U.Count Then If lst_kq.Count = 0 Then lst_kq.Add(lst_key_tmp) Else 'Không add các siêu khóa For j As Integer = 0 To lst_kq.Count - 1 If list_in(lst_kq(j), lst_key_tmp) Then test = 0 End If Next If test = 1 Then lst_kq.Add(lst_key_tmp) End If End If End If Next Return lst_kq 21 End If End Function c. Tìm phủ tối tiểu Private Function Tim_Phu_TT(ByVal lst_F As List(Of F)) As List(Of F) 'Chuyển về dạng vế phải 1 thuộc tính Dim lst_tmp As New List(Of Strin