Bảo toàn 3NF bảo toàn phụ thuộc hàm

Một phần của tài liệu (LUẬN văn THẠC sĩ) lược đồ cơ sở dữ liệu chuẩn hóa (Trang 25)

6. Cấu trúc của luận văn

1.7. Bảo toàn 3NF bảo toàn phụ thuộc hàm

Algorithm 3NF

Function: Chuẩn hóa 3NF không tổn thất và bảo toàn PTH. Input: LĐQH p = (U,F)

Output: Các LĐQH 3NF (U1,K1),(U2,K2),...,(Us,Ks) thoả

RREL(U): R[U1]R[U2]...R[Us] = R K1, K2,..., Ks - khoá của các lược đồ tương ứng

F {F+[Ui] | i = 1,2,...,s} Method

1. Tìm một phủ tối thiểu của F:

G = {K1A1, K2A2,..., KmAm}

2. Ghép các PTH có cùng vế trái trong G để thu được phủ

G = {K1X1, K2X2,..., KsXs}. 3. /* Xét phép tách  = (K1X1,...,KsXs).

Nếu chứa một siêu khóa nào đó của p

thì return {(K1X1,K1),...,(KsXs,Ks)}

nếu không

return {(K1X1,K1),...,(KsXs,Ks),(K,K)}

với K là một khóa của p. */

construct  = (K1X1,K2X2,...,KsXs); for each component V = KiXi in  do if V+ = U then // V = KiXi là siêu khóa return {(K1X1,K1),...,(KsXs,Ks)}; endif; endfor; K = Key(U,F); return {(K1X1,K1),...,(KsXs,Ks),(K,K)}; End 3NF

CHƯƠNG 2 - CÁC THUẬT TOÁN VỀ CHUẨN HÓA DỮ LIỆU QUAN HỆ

Trong chương này tôi sẽ trình bày các thuật toán của đại số quan hệ, thuật toán quản lý phụ thuộc hàm, các thuật toán tìm bao đóng và các thuật toán tìm khóa gồm các thuật toán sau:

2.1. Các thuật toán của đại số quan hệ

Các thuật toán của đại số quan hệ gồm:

2.1.1 Phép chọn

Algorithm Selection

Function: Thực hiện phép Chọn

Format: P = R(e) Input: - Quan hệ R(U)

- Biểu thức chọn e trên U.

Output: - Quan hệ P(U) = R(e) = {tR | Sat(t,e)} Method

// Tạo lập quan hệ P tương thích với R

Create(P,Attr(R)); for each tuple t in R with Sat(t,e) do

add t to P ; endfor;

return P; end Selection.

Độ phức tạp tính toán: Thuật toán duyệt r bộ, phép kiểm tra Sat(t, e) kiểm tra trên n thuộc tính, tổng cộng cần O(n.r) phép kiểm tra. [1,2]

2.1.2 Phép chiếu

Algorithm Projection

Function: Thực hiện phép Chiếu

Format: P = R[X]

Input: - Quan hệ R(U)

Output: - Quan hệ R[X]={t.X | tR} Method

Create(P,X);

for each tuple t in R with t.X not_in P do add t.X to P ; endfor; return P; end Projection.

Độ phức tạp tính toán: Giả sử mỗi lần thuật toán chỉ nạp được 1 bộ vào quan hệ kết quả P. Để kiểm tra bộ t.X có trong P ta cần tối đa r phép so sánh theo n thuộc tính. Vậy độ phức tạp tính toán là O(n.r2). [1,2]

2.1.3 Kết nối tự nhiên

Algorithm Join

Function: Thực hiện phép Kết nối tự nhiên hai quan hệ.

Format: P = RS

Input: - Quan hệ R(U)

- Quan hệ S(V)

Output: - Quan hệ RS={uv | uR,vS,u.M = v.M, M = U

 v} Method

X = Attr(R)  Attr(S); M = Attr(R)  Attr(S); Create(P,X);

for each tuple u in R do

for each tuple v in S with (u.M = v.M) do add uv to P ; endfor; endfor; return P; end Join.

Độ phức tạp tính toán: Giả sử hai quan hệ R và S có k thuộc tính chung, khi đó độ phức tạp tính toán sẽ là O(r.s.k) thao tác trên bộ. [1,2]

2.1.4 Phép hợp

Algorithm Union

Function: Thực hiện phép Hợp hai quan hệ

Format: P = R+S Input: - Quan hệ R(U)

- Quan hệ S(U)

Output: - Quan hệ R+S = {t | tR  tS} Method

P := R;

for each tuple v in S with (v not_in R) do add v to P ; endfor;

return P; end Union.

Độ phức tạp tính toán: Phép kiểm tra v thuộc R đòi hỏi r lần duyệt và so sánh trên n thuộc tính. Vậy độ phức tạp tính toán sẽ là O(s.r.n) thao tác trên bộ. [1,2]

2.1.5 Phép giao

Algorithm Intersection

Function: Thực hiện phép giao hai quan hệ

Format: P = R & S Input: - Quan hệ R(U)

- Quan hệ S(U)

Output: - Quan hệ R & S = { t | t  R  t  S } Method

Create(P,Attr(R)); for each tuple u in R with (u in S) do add u to P; endfor; return P; end Intersection. Độ phức tạp tính toán: O(s.r.n). [1,2]

2.1.6 Phép trừ

Algorithm Substraction

Function: Thực hiện phép Trừ hai quan hệ

Format: P = R-S Input: - Quan hệ R(U)

- Quan hệ S(U)

Output: - Quan hệ R - S = {t | t  R  t  S} Method

Create(P,Attr(R)); for each tuple u in R

with (u not_in S) do add u to P; endfor; return P; end Substraction. Độ phức tạp tính toán: O(s.r.n). [1,2] 2.1.7 Phép chia Algorithm Division

Function: Thực hiện phép Chia hai quan hệ

Format: P = R:S Input: - Quan hệ R(U)

- Quan hệ S(V)

Output: Quan hệ R:S = {t.M | tR,(t.M)S  R, M = U-V}

Method

M = Attr(R)-Attr(S);

c := Card(S);//số bộ của S

Create(P,M);

for each tuple t in R with (t.M not_in P) do

d := 0;//khởitạo biến đếm

for each tuple v in S if (t.M)v in R then d := d + 1 else breakfor; endif; endfor; if d = c then add t.M to P;

endif; endfor; return P; end Division.

Độ phức tạp tính toán: Thuật toán duyệt r bộ của quan hệ R. Phép kiểm tra t.M thuộc P đòi hỏi r lần duyệt và so sánh trên n thuộc tính. Tiếp đến là duyệt s lần các bộ v của quan hệ S và kiểm tra (t.M)*v có trong R. Vậy độ phức tạp tính toán sẽ là O(r2.s.n) thao tác trên bộ. [1,2]

2.2. Các thuật toán quản lý tập phụ thuộc hàm.

Các thuật toán quản lý phụ thuộc hàm gồm:

2.2.1 Thuật toán tìm phủ thu gọn tự nhiên của tập PTH F.

Định nghĩa: Cho hai tập PTH F và G trên cùng một tập thuộc tính U. G là phủ

thu gọn tựnhiên của F nếu

1. G là một phủ của F, và

2. G có dạng thu gọn tự nhiên theo nghĩa sau:

2a. Hai vế trái và phải của mọi PTH trong G rời nhau (không giao nhau.) f  G: LS(f)  RS(f) = 

2b. Các vế trái của mọi PTH trong G khác nhau đôi một. f, g  G: f  g  LS(f)  LS(g)

Thuật toán

Algorithm Natural_Reduced

Function: Tính phủ thu gọn tự nhiên của tập PTH

Format: Natural_Reduced(F) Input: - Tập PTH F

Output: - Một phủ thu gọn tự nhiên G của F

(i) G  F (ii)  LR  G: L  R =  (iii) LiRi,LjRjG: ij  LiLj Method G := ; for each FD L  R in F do Z := R - L;

if Z  then if there is an FD L  Y in G then replace L  Y in G by L  YZ else add L  Z to G; endif; endif; endfor; return G; end Natural_Reduced.

Độ phức tạp của thuật toán: Trong [2] độ phức tạp của thuật toán là O(mn) với

m là số lượng PTH trong tập F và n là số lượng thuộc tính trong U. [1.2]

2.2.2 Thuật toán tìm phủ không dư của tập PTH F.

Định nghĩa: Cho hai tập PTH F và G trên tập thuộc tính U. G được gọi là phủ

không dưcủa F nếu

(i) G là một phủ của F, và

(ii) G có dạng không dư theo nghĩa sau: gG: G \{g} ≢G

Thuật toán

Algorithm Nonredundant

Function: Tính phủ không dư

Format: Nonredundant(F) Input: - Tập PTH F

Output: - Một phủ không dư G của F

(i) G  F

(ii)  g G: G-{g} ! G Method

U := Attr(F); // Tập thuộc tính của F

G := F; for each FD g: L  R in F do if R  Closure(U,G-{g},L) then G := G – {g}; endif; endfor; return G;

end Nonredundant.

2.2.3 Thuật toán tìm phủ thu gọn trái của tập PTH.

Định nghĩa: Cho hai tập PTH F và G trên tập thuộc tính U. G được gọi là phủ

thu gọn tráicủa F nếu (i) G là một phủ của F, và

(ii) (LRG,AL): G\{LR}{L\AR} ≢G

Thuật toán

Để ý rằng AL ta có L\A L, nên

g: LRG,AL): G\{g}{L\AR}╞ LR, do đó ta chỉ cần kiểm tra G ╞ L\AR ? [1,2]

Algorithm Left_Reduced

Function: Tính phủ thu gọn trái của tập PTH

Format: Left_Reduced(F) Input: - Tập PTH F

Output: - Một phủ thu gọn trái G của F

(i) G  F

(ii)  g:LR G,AL: G-{g}{L-{A}R}!G Method

U := Attr(F);// Tap thuoc tinh cua F G := F;

for each FD g:L  R in F do X := L;

for each attribute A in X do if R  Closure(U,G,L-{A}) then delete A from L in G; endif; endfor; endfor; return G; end Left_Reduced.

Định nghĩa: Cho hai tập PTH F và G trên tập thuộc tính U. G được gọi là phủ

thu gọn phảicủa F nếu (i) G là một phủ của F, và

(ii) (LRG, AR): G\{LR}{LR\A} ≢G

Thuật toán

Algorithm Right_Reduced

Function: Tính phủ thu gọn phải của tập PTH

Format: Right_Reduced(F) Input: - Tập PTH F

Output: - Một phủ thu gọn phải G của F

(i) G  F

(ii) g:LRG,AR:G-{g}{LR-{A}}!G Method

U := Attr(F);// Tập thuộc tính của F

G := F;

for each FD g:L  R in F do X := R;

for each attribute A in X do

if A in Closure(U,G-{g}{LR-{A}},L) then delete A from R in G;

endif; endfor; if R =  then delete L  R from G; endif; endfor; return G; Right_Reduced.

2.2.5 Thuật toán tìm phủ thu gọn của tập PTH F.

Định nghĩa: Cho hai tập PTH F và G trên tập thuộc tính U. G được gọi là phủ

thu gọn của F nếu G đồng thời là phủ thu gọn trái và thu gọn phải của F. [1,2]

Function: Tính phủ thu gọn của tập PTH

Format: Reduced(F) Input: - Tập PTH F

Output: - Một phủ thu gọn của F

Method

return Right_Reduced(Left_Reduced(F)); end Reduced.

2.3. Các thuật toán tính bao đóng.

Định nghĩa: Cho tập PTH F trên tập thuộc tính U và một tập con các thuộc

tính X trong U. Bao đóng của tập thuộc tính X, ký hiệu X+ là tập thuộc tính

X+ = {A U | X  AF+}

Thuật toán

Algorithm Closure

Function: Tính bao đóng của tập thuộc tính.

Format: Y = Closure(U,F,X) Input: - LĐQH p =(U,F) - Tập thuộc tính X  U Output: - Y = X+ = { A  U | XA  F+ } Method Y := X; repeat Z := Y; for each FD L  R in F do if L  Y then Y := Y  R; endif; endfor; until Y=Z; return Y; end Closure.

Độ phức tạp tính toán Giả sử mỗi lần lặp trong repeat ta chỉ thêm được 1 thuộc tính. Khi đó repeat sẽ được lặp tối đa n lần. Mỗi lần lặp ta phải duyệt toàn bộ m

phụ thuộc hàm để thực hiện các thao tác trên các tập chứa tối đa n thuộc tính.

Vậy độ phức tạp tính toán sẽ là O(n2m). [1,2]

2.4. Các thuật toán khóa

Tư tưởng: Xuất phát từ một siêu khóa K tùy ý của LĐQH, duyệt lần lượt các thuộc tính A của K, nếu bất biến (K{A})+= U được bảo toàn thì loại A khỏi K.

Có thể thay kiểm tra (K{A})+= U bằng kiểm tra A (K{A})+. [2]

Algorithm Key

Function: Tìm một khóa của LĐQH

Format: Key(U,F) Input: - Tập thuộc tính U - Tập thuộc PTH F Output: - Khóa K U thỏa (i) K+ = U (ii) AK: (K-{A})+  U Method K := U;

for each attribute A in U do if A (K-{A})+ then K := K-{A} endif; endfor; return K; end Key.

Độ phức tạp tính toán Trong thuật toán duyệt n thuộc tính, với mỗi thuộc tính thực hiện phép lấy bao đóng với độ phức tạp n2m. Tổng hợp lại, độ phức tạp

tính toán của thuật toán là O(n3m). [1,2]

Trong chương này tôi sẽ trình bày cài đặt và ứng dụng cho các thuật toán theo hướng đối tượng cho thiết kế lớp tập hợp Set và lớp lược đồ quan hệ RSC gồm:

3.1. Tiếp cận hướng đối tượng cho thiết kế

Theo tiếp cận hướng đối tượng ta có thể thiết kế và cài đặt một kiểu dữ liệu mới. Luận văn sẽ tập trung thiết kế ba kiểu dữ liệu phục vụ cho các chương trình xử lý các tập là:

 Lớp tập hợp Set

 Lớp lược đồ quan hệ RSC

3.2. Thiết kế lớp tập hợp Set 3.2.1 Các thuộc tính của lớp Set 3.2.1 Các thuộc tính của lớp Set

Ta định nghĩa kiểu dữ liệu BS như sau:

const int __SETSIZE = 26; typedef bitset<__SETSIZE> BS;

Trong lớp Set thuộc tính Data được định nghĩa là:

BS Data;

Như vậy, Data là trường dữ liệu chứa 0-25 bit

3.2.2 Các phương thức của lớp Set

Tạo tử (constructor)

Cú pháp

inline Set() { Data.reset();

}

Ý nghĩa: Khởi tạo tập rỗng

inline Set(const string s) {

Data.reset();

for (int i = 0; i < s.length(); ++i)

if (IsAlpha(s[i]))

Data.set(Code(s[i]));

}

Ý nghĩa: Khởi tạo Set nhận giá trị từ chuỗi s Ví dụ: Set x(“ABC”);

Khi đó x chứa 2 phần từ A, B, C

Cú pháp

inline Set(const Set &x) {

Data = x.Data; }

Ý nghĩa: Khởi tạo Set nhận giá trị của tập x cho trước Ví dụ:

Set x(“ABC”);

Set y(x);

Khởi tạo x chứa 3 phần từ A, B, C

Set y(x) khởi tạo tập y nhận các giá trị của tập x là 3 phần từ A, B, C Cú pháp

inline void Reset() {

Data.reset();

}

Ý nghĩa: Reset một tập thành tập rỗng

Toán từ gán

inline void operator =(const string s) { Data.reset();

for (int i = 0; i < s.length(); ++i) if (IsAlpha(s[i]))

Data.set(Code(s[i])); }

Ý nghĩa : Gán một chuỗi từ tập x

Lấy giá trị của tập hợp

Cú pháp

inline char operator[](int i) const {

if (i >= 0 && i < __SETSIZE) {

if (Data[i])

return (Data[i]) ? ToAlpha(i) : NULL; }

return NULL; }

Ý nghĩa: Lấy phần từ thứ i cuả tập hợp.

Kiểm tra tập hợp có phải là tập rỗng hay không

Cú pháp

inline bool Empty() const {return Data.none();}

Ý nghĩa:

Kiểm tra một phần tử có thuộc tập hợp hay không

Cú pháp

inline bool IsIn(char e) {

if (IsAlpha(e)) return Data[Code(e)]; return 0; } Lực lượng của tập hợp Cú pháp

inline int Card() const {return Data.count();

Ý nghĩa: trả về số của tập hợp

Thêm phần tử vào tập hợp

inline void Ins(char e) { if (IsAlpha(e))

Data.set(Code(e)); }

Ý nghĩa : Thêm phần từ e vào tập x

Xóa phần từ

Cú pháp

inline void Del(char e) { if (IsAlpha(e)) Data.reset(Code(e)); } Ý nghĩa : Xóa phần tử e từ tập hợp Thêm phần tử Cú pháp

inline void Add(char e) {Ins(e);

Ý nghĩa: Thêm phần tử e vào tập hợp

3.2.3 Các phép toán tập hợp

Hợp của hai tập hợp

Cú pháp

Set operator +(const Set &y) const { Set z(*this);

z.Data |= y.Data; return z;

}

inline void operator +=(const Set &y) { *this = *this + y;

}

Ý nghĩa: Trả về hợp của 2 tập hợp

Giao của hai tập hợp

Cú pháp

Set operator *(const Set &y) const { Set z(*this);

z.Data &= y.Data; return z;

}

inline void operator *=(const Set &y) { *this = *this * y;

}

Ý nghĩa: Trả về giao của 2 tập hợp

Hiệu củahai tập hợp

Cú pháp

Set operator -(const Set &y) const { Set z;

for (int i = 0; i < __SETSIZE; ++i) if (Data[i] && (!y.Data[i]))

z.Data[i] = 1; return z;

}

inline void operator -=(const Set &y) {

*this = *this - y;

}

Ý nghĩa: Trả về hiệu của 2 tập hợp

So sánh hai phần tử So sánh bằng

Cú pháp

inline bool operator ==(const Set & y) const {

return Data == y.Data;

}

Ý nghĩa: So sánh hai tập hợp có bằng nhau hay không

So sánh khác

Cú pháp

inline bool operator !=(const Set & y) const {

return Data != y.Data;

}

Ý nghĩa: So sánh hai tập hợp có khác nhau hay không

So sánh nhỏ hơn hoặc bằng

Cú pháp

inline friend bool operator <=(const Set & x, const Set & y){ for (int i = 0; i < __SETSIZE; ++i)

if (x.Data[i] && (!y.Data[i])) return false;

return true; }

Ý nghĩa: So sánh hai tập hợp có nhỏ hơn hoặc bằng nhau không.

So sánh lớn hơn hoặc bằng

Cú pháp

inline friend bool operator >=(const Set & x, const Set & y){

return y <= x;

}

Ý nghĩa: So sánh hai tập hợp có lớn hơn hoặc bằng nhau không.

So sánh nhỏ hơn

Cú pháp

friend bool operator <(const Set & x, const Set & y) { return((x <= y) && (x != y));

}

Ý nghĩa: So sánh hai tập hợp có nhỏ hơn không

So sánh lớn hơn

Cú pháp

inline friend bool operator >(const Set & x, const Set & y) {

return y < x;

}

Ý nghĩa: So sánh hai tập hợp có lớn hơn không

Hiển thị

Cú pháp

friend ostream & operator <<(ostream & os, const Set & s) { if (s.Empty()) {

os << "{}"; return os; }

for (int i = 0; i < __SETSIZE; ++i) { if (s.Data[i]) os << ToAlpha(i); } return os; } Ý nghĩa: Hiển thị các phần tử ra màn hình Cú pháp

cout << msg; if (Empty()) {

cout << "{}"; return; }

for (int i = 0; i < __SETSIZE; ++i) { if (Data[i])

cout << ToAlpha(i); }

} }

Ý nghĩa: Hiển thị các phần tử ra màn hình và kèm theo thông báo msg

Ví dụ: Chương trình Demoset.cpp thực hiện các thao tác như sau: 1. Khai báo tập x, y

2. So sánh tập x có lớn hơn hoặc bằng tập y hay không 3. Hiển thị ra màn hình tập x, y

Như vậy ta thu được

/****************************************** Demoset.cpp *************************************************/ #include <iostream> #include <fstream> #include <bitset> using namespace std;

const int __SETSIZE = 26; const int __UNIT = 16;

typedef bitset<__SETSIZE> BS; class Set { protected: BS Data; public: inline Set() { Data.reset(); }

inline Set(const string s) { Data.reset();

for (int i = 0; i < s.length(); ++i) if (IsAlpha(s[i]))

Data.set(Code(s[i])); }

inline Set(const Set &x) { Data = x.Data;

}

inline void Reset() {

Data.reset();

}

inline void operator =(const Set & y) { Data = y.Data;

}

inline void operator =(const string s) { Data.reset();

for (int i = 0; i < s.length(); ++i) if (IsAlpha(s[i]))

Data.set(Code(s[i])); }

inline char operator[](int i) const { if (i >= 0 && i < __SETSIZE) {

if (Data[i])

return (Data[i]) ? ToAlpha(i) :

NULL;

}

return NULL; // (char)0; }

inline bool Empty() const {return Data.none();}

inline bool IsIn(char e) {

if (IsAlpha(e))

return Data[Code(e)];

return 0;

}

inline bool Has(char e) {return IsIn(e);}

Một phần của tài liệu (LUẬN văn THẠC sĩ) lược đồ cơ sở dữ liệu chuẩn hóa (Trang 25)

Tải bản đầy đủ (PDF)

(73 trang)