求函数依赖集F的极小依赖集和检验F是否为极小依赖集的算法 Java实现

广东工业大学 数据库系统概论

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
代码实现:

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Scanner;

/**
 * 对F进行极小化处理,获得最小依赖集
 * @author Riyad
 */
public class MinimalCover
{
	private Scanner scan = new Scanner(System.in);
	
	ArrayList<String> left = new ArrayList<String>();
	ArrayList<String> right = new ArrayList<String>();
	
	/**
	 * 输入属性集总体U
	 * @return 属性集总体的字符串
	 */
	private String inputU()
	{
		System.out.print("请输入属性集U(例如:A, B, C, D, E):");
		String str = scan.nextLine();
		String temp = str.replaceAll(",", "");
		String u = temp.replaceAll(" ", "");
		
		return u;
	}
	
	/**
	 * 输入函数依赖集
	 */
	private void inputF()
	{
		System.out.print("请输入依赖关系的个数:");
		int num = scan.nextInt();
		
		System.out.println("输入函数依赖集F:");
		for(int i = 1; i <= num; i++)
		{
			System.out.print("请输入第" + i + "个函数依赖左边的值:");
			String valueLeft = scan.next();
			left.add(valueLeft);
			
			System.out.print("请输入第" + i + "个函数依赖右边的值:");
			String valueRight = scan.next();
			right.add(valueRight);
		}
	}
	
	/**
	 * 对所有函数依赖右边的值进行拆分
	 */
	private void checkY()
	{
		for(int i = 0; i < left.size(); )
		{
			int length = right.get(i).length();
			
			if(length > 1)
			{
				for(int j = 0; j < length; j++)
				{
					left.add(left.get(i));
					right.add(String.valueOf(right.get(i).charAt(j)));
				}
				
				left.remove(i);
				right.remove(i);
				
				continue;
			}
			
			i++;
		}
	}
	
	/**
	 * 检查F中各函数依赖并对符合条件的函数依赖进行删减
	 * @param u 属性集总体U
	 */
	private void check(String u)
	{
		ArrayList<String> oldLeft = new ArrayList<String>();
		ArrayList<String> oldRight = new ArrayList<String>();
		
		//对原来的函数依赖进行备份
		for(int i = 0; i < left.size(); i++)
		{
			oldLeft.add(left.get(i));
			oldRight.add(right.get(i));
		}
		
		for(int i = 0; i < left.size(); )
		{
			String x = left.get(i);
			String a = right.get(i);
			
			left.remove(i);
			right.remove(i);
			
			String closure = outputClosure(x, u);
			
			if(closure.contains(a)) //如果A属于X的闭包,则原来的函数依赖也需删去对应的值,以保持同步
			{
				oldLeft.remove(i);
				oldRight.remove(i);
				
				continue;
			}	
			else //否则,则复原为原来的函数依赖
			{
				left.clear();
				right.clear();
				
				for(int j = 0; j < oldLeft.size(); j++)
				{
					left.add(oldLeft.get(j));
					right.add(oldRight.get(j));
				}
				
				i++;
			}
		}
	}
	
	/**
	 * 检查F中各函数依赖左边的值,并对符合条件的值进行替换
	 * @param u 属性集总体U
	 */
	private void checkX(String u)
	{
		for(int i = 0; i < left.size(); i++)
		{
			int length = left.get(i).length();
			
			if(length > 1)
			{
				String x = left.get(i);
				
				for(int j = 0; j < length; )
				{
					char b = x.charAt(j);
					String bj = String.valueOf(b);
					
					//去掉原来X中的Bj
					String newX = x.replace(bj, "");
					
					String closure = outputClosure(newX, u);
					
					if(closure.contains(right.get(i)))
					{
						x = newX;
						left.set(i, newX);
						continue;
					}
					
					j++;
				}
			}
		}
	}
	
	/**
	 * 输出求得的闭包
	 * @param x 属性集X
	 * @param u 属性集总体U
	 * @return 所求得的闭包
	 */
	private String outputClosure(String x, String u)
	{
		String lastOne = null;
		
		ArrayList<String> oldLeft = new ArrayList<String>();
		ArrayList<String> oldRight = new ArrayList<String>();
		
		//由于求闭包操作会删去原来函数依赖中的部分函数依赖,需对原来的函数依赖进行备份
		for(int i = 0; i < left.size(); i++)
		{
			oldLeft.add(left.get(i));
			oldRight.add(right.get(i));
		}
		
		while(true)
		{
			lastOne = x;
			
			for(int i = 0; i < left.size(); i++)
			{	
				if(x.contains(left.get(i)))
				{
					x += right.get(i);
					left.remove(i);
					right.remove(i);
				}
			}
			
			x = deleteRepeat(x);
			
			if(lastOne.equals(x) || x.equals(u)) 
				break;
		}
		
		//操作完成后,清除现存的函数依赖,恢复原函数依赖
		left.clear();
		right.clear();
		
		for(int j = 0; j < oldLeft.size(); j++)
		{
			left.add(oldLeft.get(j));
			right.add(oldRight.get(j));
		}
		
		return x;
	}
	
	/**
	 * 删除字符串中的重复字符
	 * @param str 要进行操作的字符串
	 * @return 删去重复字符后的字符串
	 */
	private String deleteRepeat(String str)
	{
		String deleted = "";
		
		HashSet<Character> noRepeat = new HashSet<Character>();
		
		for(int i = 0; i < str.length(); i++)
			noRepeat.add(str.charAt(i));
		
		Character[] ch = new Character[noRepeat.size()];
		Character[] array = noRepeat.toArray(ch);
		
		for(Character s : array)
			deleted += s;
		
		return deleted;
	}
	
	public static void main(String[] args)
	{
		MinimalCover mc = new MinimalCover();
		
		String u = mc.inputU();
		mc.inputF();
		
		mc.checkY();
		mc.check(u);
		mc.checkX(u);
		
		System.out.print("F的最小依赖集Fm = {");
		for(int i = 0; i < mc.left.size(); i++)
		{
			System.out.print(" " + mc.left.get(i) + "->" + mc.right.get(i) + " ");
		}
		System.out.println("}");
	}
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值