【数据库】求属性闭包的实现

#求属性闭包的实现

属性闭包:

关系模式 R < U , F > R<U,F> R<U,F>中, U U U代表全部属性集合, U U U为一组函数依赖关系。
现设属性集 X X X属于 U U U,对 X X X求属性闭包,即为根据推导规则从属性集合 X X X推导出属性集合(闭包) X F + XF^+ XF+

###问题描述:
对于给定的属性集合U,函数依赖集F,都以string类型表示,求某一属性集合X的属性闭包

例题:U={ABCDE},F={A→B, B→C,DA->BC,A->BC,DB->C}, 求属性BC的闭包。

求属性闭包的算法

针对上述例题来讲:

  1. X i = B C X_i=BC Xi=BC,求取 X i X_i Xi的子集(这里不包含空集而且子集划分为只要元素不同,不考虑顺序),为 B , C , B C B,C,BC B,C,BC,遍历函数依赖集找到左部为 X i X_i Xi的子集部分,找到把函数依赖的右部加入 P P P.
  2. X i + 1 = X i U P X_{i+1}=X_iUP Xi+1=XiUP,判断 X i + 1 X_{i+1} Xi+1是否和 X i X_i Xi或者和 U U U相等,若相等跳出循环, X i + 1 X_{i+1} Xi+1即为所求闭包,不相等调到步骤1.

思路:

首先是分割字符串提取信息保存函数依赖关系。
对于函数依赖要明确的是如何存储函数依赖。
第一考虑的是用图的邻接矩阵来存储属性之间的依赖关系,但发现用图的思路去思考问题有错误的地方:若AD->C,并不能化为A->C,D->C;所以采用MultiMap保存映射关系。

A->DC 可以变为A->D,A->C
是因为在关系模式中属性列A有相等的两行,属性列DC都有对应位置相等的两行。
但DC->A,不能变化为D->A,C->A.
是因为在关系模式中要求属性列D和C同时有相等的两行时,属性列A也有相等的两行才成立。但D->A,C->A,成立的条件中没有同时的条件,所以上述是不相等的。

####MultiMap
与 map 类似,所不同的是它允许重复键.
基本使用方法:

1.定义:

multimap<string, string>Map;

2.插入:

Map.insert(make_pair("we","student"));

3.遍历:

	for (multimap<string, string>::iterator it = Map.begin(); it != Map.end(); it++)
	{
	cout <<(*it).first<< endl;
	cout << (*it).second << endl;

	}

4.多值查找:

typedef std::multimap<string, string>::iterator it;
	pair<it, it>res;
	res = map.equal_range("we");
	while (res.first != res.second)
	{
		cout << res.first->second << endl;
		++res.first;
	}

Note:

1.vector重载的赋值运算符必须要求顺序内容和长度都相等
2.二维数组的传地址问题:
//void Process(string F,int (*FD)[MaxLen])
void Process(string F, int FD[][MaxLen])
3.s.substr(0,5);
//获得字符串s中 从第0位开始的长度为5的字符串,默认时的长度为从开始位置到尾.

代码:

注:没有做输入非法处理,假定输入合法

#include<iostream>
#include<vector>
#include<map>
#include<boost/algorithm/string.hpp>
#include<string>

using namespace std;
using namespace boost;
const int  MaxLen = 10;
class ClosePaket {
private:
	
	string Attribute;
	int len;
	multimap<string, string>FD;
	
public:
	/*初始化*/
	void Init(string a)
	{
		Attribute = a;
		sort(Attribute.begin(),Attribute.end());//便于排序
	}

	/*处理函数依赖关系,并将其保存到Map中
	@param	F: 函数依赖关系表示的字符串
	@param	FD:保存依赖关系的Map*/
	void Process(string F)
	{
		vector<string>strVec;
		split(strVec, F, is_any_of(","));//分割成A->BC
		for (size_t i = 0; i < strVec.size(); i++)
		{
			vector<string>str;
			cout << strVec[i] << endl;
			//把连续多个分隔符当作一个token_compress_on
			split(str, strVec[i], is_any_of("->"), token_compress_on);//分割成 A || BC
			//其中这里str[0]为依赖关系的前部分(A),str[1]为依赖关系的后半部分(BC)
			//cout << "size:" << str.size() << endl;
			if (str.size() != 2)cout << "分割字符串出错!!" << endl;
			FD.insert(make_pair(str[0], str[1]));
		}
		/*for (multimap<string, string>::iterator it = FD.begin(); it != FD.end(); it++)
		{
			cout << (*it).first << endl;
			cout << (*it).second << endl;
		}*/
	}
	/*求取dst的子串并返回子串数组vector*/
	vector<string> SubString(string dst)
	{
		vector<string>sub;
		for (size_t i = 0; i <dst.size(); i++)
		{
			for (size_t j = 1; j <= dst.size() - i; j++)
			{
				sub.push_back(dst.substr(i, j));
			}
		}
		/*for (size_t i = 0; i < sub.size(); i++)
			cout << sub[i] << endl;*/
		return sub;
	}
	/*使tem中插入不重复字符
	***在tem中插入tem中不曾出现的字符,而不是字符串
	@param	tem:被插入的字符串
	@param	x:要插入的字符串*/
	void insert(string &tem,string x)
	{
		for (size_t i = 0; i < x.size(); i++)
		{
			int flag = 0;
			for (size_t j = 0; j < tem.size(); j++)
			{
				if (tem[j] == x[i])flag = 1;
			}
			if (flag == 0)
				tem += x[i];
		}
	}
	/*求属性集X的闭包
	返回属性闭包表示的字符串,若失败返回空串
	1.判断init是否等于属性集总体
	2.遍历Map寻找key为init的子集,找到则把value加到tem
	3.判断tem和init是否相等
	@param dst:	属性集*/
	string GetClosePacket(string dst)
	{
			string init = dst;//init=x(i)
			string tem;//tem=x(i+1)
			while (true)
			{
				//判断是否等于属性集总体
				if (init == Attribute) {  return init; }
				tem = "";
				tem = init;
				vector<string>sub = SubString(init);
				for (size_t i = 0; i < sub.size(); i++)
				{
					//cout << "当前的键:" << sub[i] << endl;
					typedef std::multimap<string, string>::iterator it;
					pair<it, it>res;
					res = FD.equal_range(sub[i]);
					while (res.first != res.second)
					{
						
						//cout<<"找到的键值:"<< res.first->second << endl;
						insert(tem,res.first->second);
						//cout << "当前的tem值:" << tem << endl;
						++res.first;
					}
				}
				// 判断tem和init是否相等
				sort(tem.begin(),tem.end());
				sort(init.begin(),init.end());
				if (tem == init) {  return init; }
				init = tem;
			}
			return "";
		}
};

/*主函数*/
int main()
{
	
	/*属性集Attribute*/
	//char Attribute[] = { 'A','B','C','D','E' };
	string a = "ABCDE";
	string F = "AB->C,B->D,C->E,EC->B,AC->B";
	
	ClosePaket cp;
	/*初始化*/
	cp.Init(a);
	/*处理字符串F*/
	cp.Process(F);

	/*求属性AB的闭包*/
	string res = cp.GetClosePacket("EC");
	cout << "属性闭包为:" << res << endl;
	system("pause");
	return 0;
}
  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值