具有無損性串連和保持函數依賴的3NF分解C++實現,無損3nf

來源:互聯網
上載者:User

具有無損性串連和保持函數依賴的3NF分解C++實現,無損3nf

---------------------------------------------------------------------------------------------------------

本文歡迎轉載,轉載請附上連結http://blog.csdn.net/iemyxie/article/details/41246163

---------------------------------------------------------------------------------------------------------


資料庫範式對於資料庫而言無疑是非常重要的(廢話。。)本文主要內容為c++實現具有無損性串連和保持函數依賴的3NF分解。

上篇文章中已經對各個範式進行了介紹,在此不再贅述。

何為第三範式?

第三範式(3NF)要求一個資料庫表中不包含已在其它表中已包含的非主關鍵字資訊,即消除了傳遞依賴。

演算法虛擬碼

輸入:關係模式R及R上的函數依賴集F
輸出:R的3NF無損串連和保持函數依賴的分解Result
步驟如下:
1.求F的極小覆蓋Fm
右部極小化
左部極小化
規則個數極小化
2.求F的正則覆蓋Fc
合并Fm中具有相同左部的FD的右部
3.Result初始置空
for(Fc中的每個FD X->Y) do
if(Result中存在關係模式Ri,使得Ri包含於XY)then
Result=Result-Ri ∪XY
else if(Result中不存在Ri使得XY包含於Ri)then
Result=Result∪XY
if(Result中的關係模式都不包含R中的任何碼)then
將R中的一個碼添加到Result中
R^'=A | A∈R,A不在F中出現
if(R’非空) then 

將R’添加到Result中
return Result

演算法C++實現(演算法主體來自於@DarkSword)

#include<iostream>#include<string>#include<algorithm>#include<vector>#include<map>#include<stdio.h>using namespace std; string R; //關係模式vector< pair<string,string> > F; // 函數依賴集(FD)vector<string>subset; //關係模式 R 的所有子集char *temp; //求所有子集的輔助變數vector<string>candidate_key; // 所有的候選索引鍵vector<string>super_key; //所有的超鍵
bool _includes(string s1,string s2){ //判斷 s2 的每個元素是否都存在於 s1 sort(s1.begin(),s1.end()); sort(s2.begin(),s2.end()); return includes(s1.begin(),s1.end(),s2.begin(),s2.end()); // includes函數是基於有序集合的,所以先排序}bool _equal(string s1,string s2){ //判斷兩個集合是否相同 sort(s1.begin(),s1.end()); sort(s2.begin(),s2.end()); s1.erase( unique(s1.begin(),s1.end()),s1.end()); //排序去重之後判斷是否相等即可 s2.erase( unique(s2.begin(),s2.end()),s2.end()); return s1==s2;}string get_attribute_closure(const string &X, const vector< pair<string,string> > &F){ //返回屬性集X的閉包   string ans(X); //初始化 ans   string temp;   bool *vis = new bool[F.size()];   fill(vis,vis+F.size(),0);   do{temp=ans;for(int i=0;i!=F.size();++i){if(!vis[i] && _includes(ans,F[i].first) ){ vis[i]=1; ans += F[i].second;}}   }while(temp!=ans); // ans 無任何改變時終止迴圈    delete []vis;   vis=NULL;   //刪掉重複的   sort(ans.begin(),ans.end());   ans.erase( unique(ans.begin(),ans.end()),ans.end() );   return ans;}void _all_subset(int pos,int cnt,int num){ // get_all_subset()的輔助函數 if(num<=0){ temp[cnt]='\0'; subset.push_back(temp); return ; } temp[cnt]=R[pos]; _all_subset(pos+1,cnt+1,num-1); _all_subset(pos+1,cnt,num-1);}void get_all_subset(const string &R){ //求關係模式R的所有子集,儲存在subset中 subset.clear(); temp=NULL; temp=new char[R.size()]; _all_subset(0,0,R.length()); delete []temp; temp=NULL;}bool is_candidate_key(const string &s){ //判斷 s 是否是候選索引鍵 for(int i=0;i!=candidate_key.size();++i) if(_includes(s,candidate_key[i])) //如果s包含了已知的候選索引鍵,那麼s就不是候選索引鍵 return false; return true;} bool cmp_length(const string &s1,const string &s2){ //對 subset 以字串長度排序 return s1.length()<s2.length();}void get_candidate_key(const string &R, const vector< pair<string,string> > &F){//求關係模式 R基於F的所有候選索引鍵 get_all_subset(R); sort(subset.begin(),subset.end(),cmp_length); candidate_key.clear(); super_key.clear(); for(int i=0;i!=subset.size();++i){ if( _includes( get_attribute_closure(subset[i],F), R) ){ super_key.push_back(subset[i]); if(is_candidate_key(subset[i])) candidate_key.push_back(subset[i]); } }} typedef vector<pair<string,string> > vpss;vpss get_minimum_rely(const vpss &F){ //返回 F 的依賴集 vpss G(F); //使 G 中每個 FD 的右邊均為單屬性 for(int i=0;i!=G.size();++i){ if(G[i].second.length()>1){ string f=G[i].first, s=G[i].second,temp; G[i].second=s[0]; for(int j=1;j<s.length();++j){ temp=s[j]; G.push_back( make_pair(f,temp) ); } } }  int MAXN=0; for(int i=0;i!=G.size();++i) if(G[i].first.length()>MAXN) MAXN=G[i].first.length(); bool *del=new bool[MAXN];  //在 G 的每個 FD 中消除左邊冗餘的屬性 for(int i=0;i!=G.size();++i){ if(G[i].first.length()>1){ fill(del,del+G[i].first.length(),0); for(int j=0;j!=G[i].first.length();++j){ //對於第i個FD,判斷是否可消除first的第j個屬性 string temp; del[j]=1; for(int k=0;k!=G[i].first.length();++k) if(!del[k]) temp+=G[i].first[k]; if( ! _includes(get_attribute_closure(temp,G),G[i].second) ) //不可刪除 del[j]=0; } string temp; for(int j=0;j!=G[i].first.length();++j) if(!del[j])temp+=G[i].first[j]; G[i].first=temp; } } delete []del; del=NULL;  //必須先去重 sort(G.begin(),G.end()); G.erase( unique(G.begin(),G.end()),G.end());  //在 G 中消除冗餘的 FD vpss ans; for(int i=0;i!=G.size();++i){ //判斷第i個 FD 是否冗餘 vpss temp(G); temp.erase(temp.begin()+i); if( ! _includes(get_attribute_closure(G[i].first,temp),G[i].second) ) //第 i 個 FD 不是冗餘 ans.push_back(G[i]); } return ans;}vector<string> split_to_3nf(const string &R, const vector< pair<string,string> > &F){ vector< pair<string,string> > FF = get_minimum_rely(F); //儲存 F的最小依賴集到 FF // 把左部相同的 FD 用合并性合并起來 map<string,string> mp; for(int i=0;i!=FF.size();++i){ if(mp.find(FF[i].first) == mp.end() ) mp[ FF[i].first ] = FF[i].second; else mp[ FF[i].first ] += FF[i].second; }  FF.resize(mp.size()); int id=0; map<string,string>::iterator It; for(It=mp.begin(); It != mp.end(); ++It){ FF[id].first=It->first; FF[id++].second=It->second; } // 每個 FD x->y 去構成一個模式 xy vector<string> P; for(int i=0;i!=FF.size();++i) P.push_back(FF[i].first+FF[i].second);  get_candidate_key(R,F); //得到 R 的候選索引鍵 //在構成的模式集中,如果每個模式都不包含 R 的候選索引鍵,那麼把候選索引鍵作為一個模式放入到模式集中 //這樣得到的模式集是關係模式 R 的一個分解,並且這個分解既是無損分解,有能保持 FD . for(int i=0;i!=candidate_key.size();++i){ int flag=0; for(int j=0;j!=P.size();++j){ if( _includes(P[j],candidate_key[i]) ){ flag=1; break; } } if(!flag) P.push_back(candidate_key[i]); } sort(P.begin(),P.end()); P.erase( unique(P.begin(),P.end()),P.end()); return P;}void init(){ //初始化 R=""; F.clear();}void inputR(){   //輸入關係模式 R cout<<"請輸入關係模式 R:"<<endl; cin>>R;}void inputF(){  //輸入函數依賴集 F int n; string temp; cout<<"請輸入函數依賴的數目:"<<endl; cin>>n; cout<<"請輸入"<<n<<"個函數依賴:(輸入形式為 a->b ab->c) "<<endl; for(int i=0;i<n;++i){ pair<string,string>ps; cin>>temp; int j; for(j=0;j!=temp.length();++j){ //讀入 ps.first if(temp[j]!='-'){ if(temp[j]=='>')break; ps.first+=temp[j]; } } ps.second.assign(temp,j+1,string::npos); //讀入 ps.second F.push_back(ps); //讀入ps }}int main(){ freopen("in.txt","r",stdin); init(); inputR(); inputF(); vector<string> ans=split_to_3nf(R,F); cout<<"將關係模式 R 無損分解且保持依賴地分解成 3NF 模式集,如下:"<<endl; for(int i=0;i!=ans.size();++i) cout<<ans[i]<<endl;return 0;}

PS:代碼親測無誤,不要用VC6.0運行(VC6.0對STL的標準支援的不好,編譯可能會有很多Warning,運行會出錯),可以使用DEV運行。


測試資料:

input sample
abcde
2
a->b
c->d
 
abc
2
a->b
bc->a
 
abcdef
4
ab->ef
d->e
e->f
cd->ef
 
abcdef
2
ab->cd
bc->ef
 
abcdef
4
ab->ef
c->d
d->e
bc->de
 
output sample
 
ab
ace
cd
 
ab
abc
 
abcd
abe
de
ef
 
abcd
bcef
 
abc
abef
cd
de

-------------------------------------------------------------------------------------------------------------

本文歡迎轉載,轉載請附上連結http://blog.csdn.net/iemyxie/article/details/41246163

-------------------------------------------------------------------------------------------------------------


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.