数据库基础(1)关系的布尔运算:数据集的并,交,差,补和有效补运算

关系的布尔运算主要包括:并,交,差,广义笛卡尔积,补,有效补

并集

定义: 关系R和S的并集结果,由属于R或属于S的所有元组组成,其结果是一个新关系。记为:

Q = R ∪ S = {t | t ∈ R 或 t ∈ S }

例子: 注意! 这个并集求出来是不含重复元组的!例如虽然R和S都含有(a1,b2,c2),但是合并的结果中,只出现一次(a1,b2,c2)
并集

差集

定义: 关系R和S的差由属于R但不属于S的所有元组组成。记为:
Q = R - S = {t | t ∈ R 但 t ∉ S }
例子
差集

交集

定义: 关系R和S的交集结果由既属于R又属于S的所有元组组成。记为:
Q = R ⌒ S = {t | t ∈ R 且 t ∈ S }
交集

广义笛卡尔积

关系R和关系S的笛卡尔积为R中所有元组和S中所有元组的串接。
结果关系的属性个数:k1+k2 (k1和k2分别为关系S的属性数)
结果关系的元组数: m x n (m和n分别为R和S的元组数)
例子:
广义笛卡尔积

补集和有效补集

1.首先看看补集定义:

关系模式R(A1,A2,…,An), R上的关系r。
补运算:设dom( R )表示模式R上的所有元组的集合,则关系r的补为:
r的补集 = dom( R )-r
我们可以按照数学里的补集来理解,其实就是 (集合r + r的补集 = 全集) ,只不过这里的全集是关系R上的所有元组的集合
例题:
补集
这道题,我们首先要知道关系R上的全集(全部元组)是什么,然后用全集减去r,就可以得到r的补集了
R上的全集是A和B的广义笛卡尔积,即:
R=(A,B)={(a1,b1),(a1,b2),(a2,b1),(a2,b2),(a3,b1),(a3,b2)}
所以用R中的元组减去r 即可得到r补集

2.有效补集

定义

有效补集的定义看上去太麻烦,我们这里直接以一道题来讲怎么求有效补

例题
第一步 求出R: R=(A,B)={(a1,b1),(a1,b2),(a2,b1),(a2,b2),(a3,b1),(a3,b2)}

第二步 理解有效值域。关系r的有效值域是指,关系r中各个属性的取值范围。比如说我们这道题里面的r ,它的属性A的属性取值范围是(a1,a2),属性B的取值范围是(b1,b2),所以r元组的有效值域就是(A,B)={A ∈ (a1,a2) 且 B ∈ (b1,b2)}。 因此我们求有效补集的全集就不再是R,而是R*R* 中属性的值域就是r的有效值域。

第三步 根据r的有效值域和R*求r的有效补集。首先根据r的值域范围,得到R*,即,将R中只含有(a1,a2)和(b1,b2)的元组取出来(注意:不取含属性a3的元组,因为属性a3不在r的范围中),R*={(a1,b1),(a1,b2),(a2,b1),(a2,b2)}
于是,r的有效补集= R*-r ={(a1,b1),(a1,b2),(a2,b1),(a2,b2)} - {(a1,b1),(a1,b2),(a2,b1)}={(a2,b2)}

有效补的应用:当关系元组数比其有效补元组数多得多时,有效补可作为数据压缩手段。
例如:学生选课,一个班有50个学生选数据库课,3个学生不选, 则存储选修了数据库课的学生可用存储其有效补实现。

最后再来做一道例题吧

例题
(1)求补集
首先计算R,即A,B,C的笛卡尔积,R= A x B x C = {(a1,b1,c1),(a1,b1,c2),(a1,b2,c1),(a1,b2,c2),(a1,b3,c1),(a1,b3,c2),(a2,b1,c1),(a2,b1,c2),(a2,b2,c1),(a2,b2,c2),(a2,b3,c1),(a2,b3,c2)}
所以r的补集=R-r = {(a1,b1,c2),(a1,b2,c1),(a1,b2,c2),(a1,b3,c1),(a1,b3,c2),(a2,b1,c2),(a2,b2,c2),(a2,b3,c2)}
(2)求有效补
首先确定r的有效值域: r中属性A的范围是(a1,a2),属性B的范围是(b1,b2,b3),属性C的范围是(c1)
所以可以得到R*={(a1,b1,c1),(a1,b2,c1),(a1,b3,c1),(a2,b1,c1),(a2,b2,c1),(a2,b3,c1)}
因此r的有效补集=R*-r = {(a1,b2,c1),(a1,b3,c1)}

  • 15
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
好的,首先需要明确的是,LEX和YACC分别是词法分析器和语法分析器生成器。它们可以联合使用来构建编译器、解释器等程序。 我们可以使用LEX和YACC来实现一个简单的计算器,包括数值运算布尔运算。以下是一个简单的实现示例: 首先,我们需要定义LEX文件来实现词法分析器。该文件的作用是将输入的字符串分解为单个的词法单元,例如数字、操作符等。下面是一个简单的LEX文件示例: ``` %{ #include "y.tab.h" %} %% [0-9]+ { yylval.num = atoi(yytext); return NUM; } [ \t] ; \n { return EOL; } . { return yytext[0]; } %% ``` 在这个文件中,我们定义了三个词法单元:NUM、EOL和其他字符。其中,NUM表示数字,EOL表示行末,其他字符表示操作符等。 接下来,我们需要定义YACC文件来实现语法分析器。该文件的作用是将词法单元组合成语法树,然后执行计算操作。下面是一个简单的YACC文件示例: ``` %{ #include <stdio.h> #include <stdlib.h> %} %union { int num; } %token <num> NUM %token EOL %left '+' '-' %left '*' '/' %left AND OR NOT %precedence UMINUS %start calc %% calc: /* empty */ | calc expr EOL { printf("= %d\n", $2); } ; expr: NUM { $$ = $1; } | expr '+' expr { $$ = $1 + $3; } | expr '-' expr { $$ = $1 - $3; } | expr '*' expr { $$ = $1 * $3; } | expr '/' expr { $$ = $1 / $3; } | '-' expr %prec UMINUS { $$ = -$2; } | expr AND expr { $$ = $1 && $3; } | expr OR expr { $$ = $1 || $3; } | NOT expr { $$ = !$2; } ; %% int main() { yyparse(); return 0; } ``` 在这个文件中,我们首先定义了一个联合类型,用于存储词法单元的值。然后,我们定义了NUM和EOL两个词法单元,以及一些操作符的优先级和结合性。接下来,我们定义了一个起始符号calc和一个表达式expr。 在expr规则中,我们定义了各种数值运算布尔运算的语法规则,并在其中执行相应的计算操作。例如,对于加法操作,我们执行$1+3$的计算,并将结果存储在$$中。 最后,我们在main函数中调用yyparse函数来启动解析器,并执行计算操作。 要编译这个程序,我们需要使用以下命令: ``` lex calc.l yacc -d calc.y gcc lex.yy.c y.tab.c -o calc ``` 现在,我们就可以运行这个程序,并输入一些表达式来测试它了。例如,输入2+3并按下回车键,程序将输出5。输入4*5-2并按下回车键,程序将输出18。输入1 AND 0并按下回车键,程序将输出0。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值