您的位置:首页 > 编程语言 > C语言/C++

具有无损连接性的BCNF分解 C++实现

2014-11-27 11:12 183 查看
------------------------------------------------------------------------------------

欢迎转载,请附上链接

http://blog.csdn.net/iemyxie/article/details/41543169

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

何为BC范式?

BCNF是3NF基础上的一种特殊情况,每个属性不传递依赖于R的候选键(包含关系),即每个表中只有一个候选键。

算法伪代码

输入:关系模式R以及R上的函数依赖集F

输出:R的BCNF分解Result,它关于F具有无损连接性

方法:

Result = {R}

while(存在Ri包含于Result,但Ri不是BCNF)

begin

找出Ri中满足如下条件的非平凡的函数依赖:X->Y包含于Fi的闭包,且X不是Ri的超码

Result = Result -
{Ri} ∪{XY,Ri - Y}

end

return Result

算法C++实现(算法主体来自@DarkSword

#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#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函数是基于有序集合的,所以先排序
}
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;
}
string _difference(string a,string b){ //先去重,再返回 a 和 b 的差集,即 a-b
string c;
c.resize(a.size());
sort(a.begin(),a.end());
a.erase( unique(a.begin(),a.end()),a.end());
sort(b.begin(),b.end());
string::iterator It=set_difference(a.begin(),a.end(),b.begin(),b.end(),c.begin());
c.erase(It,c.end());
return c;
}
/***************将关系模式 R  无损分解成 BCNF 模式集 Update on 2014.12.10*****************/
<span style="color:#ff6600;">vector<string> split_to_bcnf(const string &R, const vector< pair<string,string> > &F){
string ans = R;
<pre name="code" class="cpp"><span style="white-space:pre">	</span>string temp;
string tempf;
vector<string> result;
int i;
string bibao;
string key="";
vector< pair<string,string> > FF = F;
int flag=0;
while(1) {
temp = ans;
bibao = get_attribute_closure(ans,FF);
get_candidate_key(ans,FF);
for(int q=0;q!=candidate_key.size();q++){
key+=candidate_key[q];
}
for(i=0;i!=FF.size();i++){
tempf=FF[i].first+FF[i].second;
if(_includes(ans,tempf)){
flag=1;
}
if( _includes(bibao,tempf) && (! _includes(FF[i].first,key))) {
result.push_back(FF[i].first+FF[i].second);
ans=_difference(ans,FF[i].second);
}
}
if(i== FF.size() && temp == ans) {
if(flag==0){
ans="";
}
if( ! (ans=="")){
result.push_back(ans);
}
break;
}
flag=0;
}
sort(result.begin(),result.end());
result.erase( unique(result.begin(),result.end()),result.end());
return result;
}
<pre name="code" class="cpp">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();
string anss;
string f;
vector<string> ans=split_to_bcnf(R,F);

for(int qqq=0;qqq!=ans.size();qqq++){

cout<<ans[qqq]<<endl;
}

return 0;
}
PS:用DEV运行,不要用VC。前文已经说过原因,不再赘述。

Updated on:2014-12-10
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息