关系规范化之分解的函数依赖保持性判定

分解的依赖保持性判定 

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

定义:对于R(U,F), R(U,F)的分解p={R1(U1,F1),(U2,F2),...,Rk(Uk,Fk)},其中,F1,F2,...Fi,分别对应为F中在R1,R2,...Rk上的函数依赖集合。

令G=F1 U F2 U F3...U Fk(多个函数依赖集合求并集),若F+==G+(其实就是如果G等于F)的话,则分解p保持函数依赖。

实质: G=F1 U F2 U F3...U Fk,判断G和原函数依赖F是否等价 
输入:R上的函数依赖集F以及R的一个分解 p={{R1,F1},{R2,F2},...,{Rk,Fk}}

输出:判断分解p的依赖保持性 

步骤:

第0步,初始化。输入R上的函数依赖集F以及R的一个分解 p={{R1,F1},{R2,F2},...,{Rk,Fk}},求出G 

第1步,检验F上的任意一个函数依赖是否能够由G通过Armstrong公理导出,及任意是否Y属于X关于G的闭包

第2步,检验G上的任意一个函数依赖是否能够由F通过Armstrong公理导出,及任意是否Y属于X关于F的闭包

第3步,若第1步和第2步均满足,则F的闭包=G的闭包 

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

那么,F1、F2、F3...Fk是什么意思以及 G=F1 U F2 U F3...U Fk如何求得呢?

Fi是R(U,F)的函数依赖集合F在各个分解Ui上的投影,G也就是全部F在各个分解Ui上的投影的并集。

π(Ui)F表示F在某个分解Ui上的投影,它是一个函数依赖集合(里面的元素是函数依赖X->Y),X,Y均属于Ui,并且形如X->Y函数依赖都在F的闭包F+上,等价于Y属于X关于F的闭包。

所以要求G,首先就要求F在各个分解上的投影。然后并起来,就是G了。这是第0步的工作。之后就按照上面介绍的步骤来就是了。

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

程序:

//分解的依赖保持性判定 
//定义:若R(U,F), R(U,F)的分解p={R1(U1,F1),(U2,F2),...,Rk(Uk,Fk)},F+=F1 U F2 U F3...U Fk,
//其中,F1,F2,...Fi,分别对应为,F中在R1,R2,...RK上的函数依赖集合。则分解p保持函数依赖 
//实质: G=F1 U F2 U F3...U Fk,判断G和原函数依赖F是否等价 
//输入:R上的函数依赖集F以及R的一个分解 p={{R1,F1},{R2,F2},...,{Rk,Fk}}
//输出:判断分解p的依赖保持性 
#include <iostream>
#include <string>
using namespace std; 

struct FunctionDependence//函数依赖 
{
	string X;//决定因素 
	string Y;	
};

void InitFD (FunctionDependence FD[],int n)
{
	//函数依赖关系初始化
	int i;
	string x,y;
	cout<<"请输入F中的函数依赖(决定因素在左,被决定因素在右)"<<endl; 
	//输入函数依赖集合F 
	for (i=0;i<n;i++)
	{		
		cin>>x>>y;
		FD[i].X=x;
		FD[i].Y=y;	
	} 
	cout<<"函数依赖集合F:"; 
	cout<<"F={" ;
	for (i=0;i<n;i++)
	{
		//显示已知的函数依赖集合F 

		cout<<FD[i].X<<"->"<<FD[i].Y;
		if (i<n-1)cout<<", ";	
	} 
	cout<<"}"<<endl; 
}
bool Match(string a,string b)//判断两个字符串是否匹配
{
	bool flag=false;
	int length1=a.length();
	int length2=b.length();
	int count=0;
	if (length1==length2)
	{
		int i=0,j=0;
		//字符串每一位是否相等 
		for (i=0;i<length1;i++)
		{
			if(a[i]==b[i])count++;
		}
		if (count==length1)
		flag=true;
	}
	return flag;
} 
bool IsIn(string f,string zz)//能够判断F中决定因素f里所有的因素是否在X中,但这样可能导致结果出现重复 
{
	bool flag1=false;
	int len1=f.length();
	int len2=zz.length();
	int k=0,t=0,count1=0;
	for (k=0;k<len1;k++)
	{
		for (t=0;t<len2;t++)
		{
			if (f[k]==zz[t])
			{
				//flag1=true;break;
				count1++;
			}
		}
	}
	if (count1==len1)
	{
		flag1=true;
	}
	else flag1=false;
	return flag1;
}
string CutAndSort(string mm)//将最终得到的闭包去除其中重复的元素,并且进行排序 
{
	int size=mm.length();
	int kk=0,ii=0;;
	string closure;
	int a[200]={0};//用来记录各个命题出现的次数
	for(kk=0;kk<size;kk++) 
	{
		a[(int)mm[kk]]++;//强制转换类型,储存各个因素的次数 
	}

	for (ii=0;ii<200;ii++)
	{
		if (a[ii]>=1)//cout<<(char)ii;
		closure+=(char)ii;
	} 
	return closure;
} 


string X_Fn(FunctionDependence FD[],int n,string &xx)
{
	string yy=xx;
	for (int i=0;i<n;i++)
	{
		if (IsIn(FD[i].X,yy)==true)
		{
			xx+=FD[i].Y;
		}		
	}
	yy=CutAndSort(yy);
	xx=CutAndSort(xx);	
	//cout<<"yy="<<yy;
	//cout<<"        xx="<<xx<<endl;
	if (xx!=yy)
	{
		X_Fn(FD,n,xx);//递归 
	}
	return xx; 
}

string FD(FunctionDependence FD[],int n,string xx)
{
	int i;
	//cout<<"\n"<<xx<<"关于F的闭包:{";
	//求X关于F的闭包
	/*
	for (i=0;i<n;i++)
	{
		if (IsIn(FD[i].X,xx)==true)
		{
			if (IsIn(FD[i].Y,xx)==false)//避免加上重复的元素 
			xx+=FD[i].Y;
			//假如有传递性 
			string temp_str=FD[i].Y;
			for (int ii=0;ii<n;ii++)
			{				
				if (Match(temp_str,FD[ii].X)==true)
				{
					xx+=FD[ii].Y;
					if (FD[i].X!=FD[ii].Y)//重中之重!!! 
					temp_str=FD[ii].Y;
				}				
			}
		} 
	}*/
	//cout<<X_Fn(FD,n,xx);
	//cout<<"}\n";
	return X_Fn(FD,n,xx);
}

string char2string(char mychar,string mystring)//将单个char转换成string类型
{
	mystring="a";//仅仅只是赋予一个初始值
	mystring[0]= mychar;
	return mystring;
} 

int main() 
{
	//第0步,初始化。输入R上的函数依赖集F以及R的一个分解 p={{R1,F1},{R2,F2},...,{Rk,Fk}},求出G 
	//0.0初始化
	cout<<"请输入关系模式R(中间无间隔,无回车)"<<endl; 	
	string A;
	cin >> A;
	int lengthR = A.length();
	cout<<"关系模式R={";
	for (int i = 0;i<lengthR;i++)
	{
		cout << A[i] ;
		if (i<lengthR-1)cout<<",";
	}
	cout<<"}"<<endl;
	
	int count = 0;
	string R[lengthR+20];
	cout<<"输入R的一个分解p(以0结束)\n";
	while (cin >> R[count])//当输入的字符串不在R中时自动跳出 
	{
		if (IsIn(R[count],A) == false) break;
		count++;
	}
	cout<<"p={";
	for (int i = 0;i<count;i++)
	{
		cout << R[i] ;
		if (i<count-1)cout<<",";
	}
	cout<<"}";
	int N;
	cout<<"\n请输入F中函数依赖的组数:"; 
	cin>>N;
	FunctionDependence fd[N];
	InitFD(fd,N);
	//0.1求出G 
	FunctionDependence G[N+30];//用来储存新的函数依赖
	string temp;
	//依此求得函数依赖集合F在各个分解上的投影
	int G_size=0;//新函数依赖集合G的大小 
	for (int i=0;i<count;i++)
	{
		//下面两层循环是排列出Ri中所有的组合,例如R3=BCD,则可能的组合有B->C,B->D,C->D,理论上有n*(n-1)/2种情况 
		for (int j=0;j<R[i].length();j++)
		{
			//得到X关于F的闭包
			string temp_A="a";//a仅仅只是一个初始值而已,没有其他意义 
			temp_A=char2string(R[i][j],temp_A);
			temp=FD(fd,N,temp_A);//R[i][j]表示第i个分解的第j位,不知道这样表示成二维数组的形式可不可以 ! 

			for (int k=0;k<R[i].length();k++)
			{
				if (j==k)continue;
				string temp_B="b";
				temp_B=char2string(R[i][k],temp_B);
				if (IsIn(temp_B,temp)==true)
				{
					G[G_size].X=R[i][j];
					G[G_size].Y=R[i][k];//得到的集合,左边右边都是原子属性 
					G_size++;
				}
			}
		}
			
	} 
	//显示G
	cout<<"F在各个分解上投影的并集G={"; 
	for (int i=0;i<G_size;i++)
	{
		cout<<G[i].X<<"->"<<G[i].Y;
		if (i<G_size-1)cout<<", ";
	} 
	cout<<"}"<<endl;
	
	//第1步,检验F上的任意一个函数依赖是否能够由G通过Armstrong公理导出,及任意是否Y属于X关于G的闭包 
	bool first_flag=0;
	int first_count=0;
	for (int i=0;i<N;i++)
	{
		if (IsIn(fd[i].Y,FD(G,G_size,fd[i].X))==true)//Y属于X关于F的闭包 G,G_size
		{
			first_count++;
			cout<<fd[i].Y<<"属于"<< fd[i].X<<"对于G的闭包"<<FD(G,G_size,fd[i].X)<<endl;
		}
	} 
	if (first_count==N) 
	{
		first_flag=1;cout<<"F上的任意一个函数依赖能够由G通过Armstrong公理导出\n"<<endl; 
	}
	//第2步,检验G上的任意一个函数依赖是否能够由F通过Armstrong公理导出,及任意是否Y属于X关于F的闭包
	bool second_flag=0;
	int second_count=0;
	for (int j=0;j<G_size;j++)
	{
		if (IsIn(G[j].Y,FD(fd,N,G[j].X))==true)//Y属于X关于F的闭包 
		{
			second_count++;
			cout<<G[j].Y<<"属于"<< G[j].X<<"对于G的闭包"<<FD(fd,N,G[j].X)<<endl;
		}
	} 
	if (second_count==G_size) 
	{
		second_flag=1;cout<<"G上的任意一个函数依赖能够由F通过Armstrong公理导出\n"<<endl; 
	}
	//第3步,若第1步和第2步均满足,则F的闭包=G的闭包 
	if (first_flag==1&&second_flag==1)cout<<"F的闭包==G的闭包,分解p具有依赖保持性!"<<endl;
	else cout<<"F的闭包!=G的闭包,分解p不具有依赖保持性!"<<endl;
	return 0;
}

结果:




  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值