关系规范化之满足第三范式3NF的函数依赖保持分解算法

满足第三范式3NF的函数依赖保持分解算法

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

输入:关系模式R和函数依赖集合F

输出:结果为满足第三范式的一个依赖保持的分解 

条件:

1.如果R中有某些属性与F的最小覆盖Fmin中的左边右边都没有关系,则这个(些)属性构成一个关系模式。如果没有就进行2 

2. 如果Fmin中有一个函数依赖涉及R中的所有属性,则输出R。否则,进行3

3.对于Fmin,其中有X->Ai这样的函数依赖,则添加XAi到一个分解集合p中,但是当X->A1,X->A2,...,X->An时(即X可与决定Fmin中多个属性),用XA1A2...An来替换之前的XAi 

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

回顾一下什么是1NF,2NF,3NF以及BCDF:http://blog.csdn.net/scnujack/article/details/6539642

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

程序:

//满足第三范式3NF的函数依赖保持分解算法
//输入:关系模式R和函数依赖集合F
//输出:结果为满足第三范式的一个依赖保持的分解 
//条件:1.如果R中有某些属性与F的最小覆盖Fmin中的左边右边都没有关系,则这个(些)属性构成一个关系模式。如果没有就进行2 
//2. 如果Fmin中有一个函数依赖涉及R中的所有属性,则输出R。否则,进行3
//3.对于Fmin,其中有X->Ai这样的函数依赖,则添加XAi到一个分解集合p中,但是当X->A1,X->A2,...,X->An时(即X可与决定Fmin中多个属性),用XA1A2...An来替换之前的XAi 
#include <iostream>
#include <string>
using namespace std;

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

struct Hash//散列 
{
	int num;//用来记录字符串出现的次数 
	string s; 
};

void Init (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<<"函数依赖集合"; 
	cout<<"F={" ;
	for (i=0;i<n;i++)
	{
		//显示已知的函数依赖集合F 
		cout<<FD[i].X<<"->"<<FD[i].Y;
		if (i<n-1)cout<<", ";	
	} 
	cout<<"}"<<endl; 
}
bool CharIsIn(char f, string zz)
{
	bool flag = false;
	int len = zz.length();
	int k = 0,  count1 = 0;
	for (k = 0;k<len;k++)
	{
			if (f == zz[k])
			{
				flag= true;;
			}
	}
	return flag;
}
string CutAndSort(string mm)//将最终得到的闭包去除其中重复的元素,并且进行排序 
{
	int size=mm.length();
	string ss="\0"; 
	int kk=0,ii=0;;
	int a[200]={0};//用来记录各个命题出现的次数
	for(kk=0;kk<size;kk++) 
	{
		a[(int)mm[kk]]++;//强制转换类型,储存各个因素的次数 
	}

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

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 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);    
    if (xx!=yy)  
    {  
        X_Fn(FD,n,xx);//递归   
    }  
    return xx;   
}  

string FD_Fun(FunctionDependence FD[],int n,string xx)
{
    //求X关于F的闭包   
	return X_Fn(FD,n,xx); 
}

//从函数依赖集F中删除某个依赖关系 left->right
void  Cut(FunctionDependence FD[],int n,string left,string right,FunctionDependence Dyna[])
{	
	int i=0,j=0,count=0;
	for (i=0;i<n;i++)
	{
		if((FD[i].X==left)&&(FD[i].Y==right))
		{
		}
		else
		{
			Dyna[count].X=FD[i].X;
			Dyna[count].Y=FD[i].Y;
			count++;
		}
	}
	cout<<"去掉"<<left<<"->"<<right;
	cout<<"后的函数依赖集F:"<<endl;
	cout<<"F={" ; 
	for(j=0;j<count;j++)
	{
		cout<<Dyna[j].X<<"->"<<Dyna[j].Y;
		if (j<count-1)cout<<",";
	}
	cout<<"}"<<endl;	
	
}

bool RA(FunctionDependence a,FunctionDependence b)//判断冗余属性
{
	if ((IsIn(a.X,b.X)==true)&&(a.Y==b.Y)) 
	{
		return true;
	}
	else return false;
} 

string StringCutChar(char f, string zz) //从中去掉一个属性
{ 
    int len = zz.length();  
    int k = 0;
    string tt;
    for (k = 0;k<len;k++)  
    {  
            if (f == zz[k])  
            {  
            }
			else 
			{
				tt+=zz[k];
			}  
    } 
	return tt;
} 

FunctionDependence Dyna[200]; 
int Fmin_Size;
void CutSameFD(FunctionDependence FD[],int n)//除去重复的函数依赖 
{
	FunctionDependence Dyna1[n+20];
	FunctionDependence Dyna2[n+20];

	int i=0,j=0,k=0,count=0,count1=0;//count2=0;
	for (i=0;i<n;i++)
	{
			for (j=0;j<count;j++)
			{
				if((FD[i].X==FD[j].X)&&(FD[i].Y==FD[j].Y))//有函数依赖重复
				{
					break;//跳过当前的函数依赖 
				} 
			}
			if (j==count)
			{
				Dyna1[count].X=FD[i].X;
				Dyna1[count].Y=FD[i].Y;
				count++; 
			}			
	}
	cout<<"去掉重复后的函数依赖集F="<<"{";
	for (k=0;k<count;k++)
	{
		//去掉重复后的函数依赖集
		cout<< Dyna1[k].X<<"->"<<Dyna1[k].Y;
		if (k<count-1)cout<<",";
	}
	cout<<"}"<<endl;
	
	for (k=0;k<count;k++)
	{
		//从第一个函数依赖X→Y开始将其从F中去掉,
		Cut( Dyna1,count,Dyna1[k].X,Dyna1[k].Y,Dyna2);
		//然后在剩下的函数依赖中求X的闭包X+,看X+是否包含Y
		cout<<Dyna1[k].X<<"关于F的闭包:";
		cout<<FD_Fun(Dyna2,count,Dyna1[k].X);//在剩下的函数依赖中求X的闭包X+
		if(IsIn(Dyna1[k].Y,FD_Fun(Dyna2,count,Dyna1[k].X))==true)//在闭包中 
		{
			cout<<"\n"<<Dyna1[k].X<<"->"<<Dyna1[k].Y<<"冗余"<<endl;
		}
		else 
		{
			cout<<"\n"<<Dyna1[k].X<<"->"<<Dyna1[k].Y<<"不冗余"<<endl;			
			Dyna[count1].X=Dyna1[k].X;
			Dyna[count1].Y=Dyna1[k].Y;
			count1++;
		}
	}
	cout<<"\n去冗余函数依赖后的函数依赖集F={";
	for (i=0;i<count1;i++)
	{
			cout<<Dyna[i].X<<"->"<<Dyna[i].Y;
			if (i<count1-1)cout<<",";
	} 
	cout<<"}"<<endl;
	//去掉冗余属性
	for (i=0;i<count1;i++)
	{
		for (j=0;j<Dyna[i].X.length();j++)
		{
			//X-Bj
			string temp_x=StringCutChar((Dyna[i].X)[j],Dyna[i].X);
			if (IsIn(Dyna[i].Y,FD_Fun(Dyna,count1,temp_x))==true)//即X->A,X=B1B2..Bm,A属于{X去掉某个其中的属性Bi的闭包} 
			{
				Dyna[i].X= temp_x;
			}
		}
			
	}
	//求得最小覆盖 
	cout<<endl; 
	cout<<"最小覆盖Fm="<<"{";
	for (k=0;k<count1;k++)
	{
			cout<<Dyna[k].X<<"->"<<Dyna[k].Y;
			if (k<count1-1)cout<<",";		
	} 
	cout<<"}"<<endl;
	Fmin_Size=count1;
} 

void SingleR(FunctionDependence FD[],int n) //使F所有函数依赖的右部分解成单一属性 
{
	int lengthR=0,i=0,j=0,k=0;
	static int D=n;
	int count=0;
	FunctionDependence  DynamicFD[D+20];//建立新的空间来存储所有的函数依赖 
	cout<<"右侧属性单一化后的函数依赖集F为:"<<endl;
	cout<<"F={" ;
	for (i=0;i<n;i++)
	{
			lengthR=(FD[i].Y).size();			
			for (j=0;j<lengthR;j++)//将右部分解成单一属性,添加到属性集合的后面 
			{
				DynamicFD[count].X=FD[i].X;
				DynamicFD[count].Y= (FD[i].Y)[j];
				count++;
			}
			
	}
	for (k=0;k<count;k++)
	{
		cout<<DynamicFD[k].X<<"->"<<DynamicFD[k].Y;	
		if (k<count-1)cout<<", ";	
	}
	
	cout<<"}"<<endl; 
	D=count; 
	CutSameFD(DynamicFD,D);


}

bool DinamicCompare(string a,Hash b[],int n)
{
	int count_dc=0;
	for (int i=0;i<n;i++)
	{
		if (a!=b[i].s)count_dc++;
	}
	if (count_dc==n) return true;
	else return false;
}

void Fmin(FunctionDependence FD[],int n)//求最小覆盖 
{
	Init(FD,n);	
	SingleR(FD,n);	
	
}

int main()
{
	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 N;
	cout<<"请输入F中函数依赖的组数:"; 
	cin>>N;
	//第一步:求出F的最小覆盖 
	FunctionDependence fd[N];
	//FunctionDependence Dyna3[N+20];
	Fmin(fd,N);

	//第二步:如果R中有某些属性与F的最小覆盖Fmin中的左边右边都没有关系,则这个(些)属性构成一个关系模式。如果没有就进行2 
	
	int count_i = 0,count=0;
	string R[lengthR+20];

	Hash left_type[lengthR+20];//用来储存Fmin的不同决定因素 
	int temp1=0,l_type=0,l_num=0;
	for (int n=0;n<Fmin_Size;n++)
	{
		if (DinamicCompare(Dyna[n].X,left_type,l_type)==false)//和之前的有相等的,跳过 
		{
			continue;
		}
		for (int nn=0;nn<Fmin_Size;nn++)
		{
			if (Dyna[n].X==Dyna[nn].X)
			{
				l_num++;
				left_type[l_type].s=Dyna[n].X;
				left_type[l_type].num=l_num;//出现的次数 
			}
		}
		l_type++;
		l_num=0;
	} 
	int k=0;
	bool my_flag=0;
	for (int i = 0;i<lengthR;i++)
	{
		while (Dyna[k].X!="\0")
		{
				if (CharIsIn(A[i],Dyna[k].X)==false&&CharIsIn( A[i], Dyna[k].Y)==false)
				{
					count_i++;
				}
				else if (CutAndSort(Dyna[k].X+Dyna[k].Y)==CutAndSort(A))
				{
					cout<<"分解就是A本身"<< CutAndSort(A)<<endl;
					my_flag=1;break;
				}
				k++;	
		} 	
		if (count_i==Fmin_Size)	
		{
			R[count]=A[i];
			count++;			
		}
		if (my_flag==1)break;
	}
	//3.对于Fmin,其中有X->Ai这样的函数依赖,则添加XAi到一个分解集合p中,但是当X->A1,X->A2,...,X->An时(即X可与决定Fmin中多个属性),用XA1A2...An来替换之前的XAi 
	if (my_flag==0)
	{
			for (int m=0;m<l_type;m++)
			{
				R[count]=left_type[m].s;//+Dyna[m].Y;
				for (int aa=0;aa<Fmin_Size;aa++)
				{
					//if (aa==m)continue;			
					if (left_type[m].s==Dyna[aa].X)
					{
						R[count]+=Dyna[aa].Y;						
					}
				}
				count++;
			}
			cout<<"满足第三范式3NF的函数依赖保持分解p={";
			for (int bb=0;bb<count;bb++)
			{
				cout<<R[bb];
				if (bb<count-1)cout<<",";
			} 
			cout<<"}"<<endl;
	}
	
	return 0;
} 



其中求最小覆盖等函数,沿用或者部分改变自之前编写的函数,如有疑问可以查看之前的文章。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值