实验二离散报告.docx

上传人:b****4 文档编号:3835458 上传时间:2023-05-06 格式:DOCX 页数:18 大小:234.96KB
下载 相关 举报
实验二离散报告.docx_第1页
第1页 / 共18页
实验二离散报告.docx_第2页
第2页 / 共18页
实验二离散报告.docx_第3页
第3页 / 共18页
实验二离散报告.docx_第4页
第4页 / 共18页
实验二离散报告.docx_第5页
第5页 / 共18页
实验二离散报告.docx_第6页
第6页 / 共18页
实验二离散报告.docx_第7页
第7页 / 共18页
实验二离散报告.docx_第8页
第8页 / 共18页
实验二离散报告.docx_第9页
第9页 / 共18页
实验二离散报告.docx_第10页
第10页 / 共18页
实验二离散报告.docx_第11页
第11页 / 共18页
实验二离散报告.docx_第12页
第12页 / 共18页
实验二离散报告.docx_第13页
第13页 / 共18页
实验二离散报告.docx_第14页
第14页 / 共18页
实验二离散报告.docx_第15页
第15页 / 共18页
实验二离散报告.docx_第16页
第16页 / 共18页
实验二离散报告.docx_第17页
第17页 / 共18页
实验二离散报告.docx_第18页
第18页 / 共18页
亲,该文档总共18页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

实验二离散报告.docx

《实验二离散报告.docx》由会员分享,可在线阅读,更多相关《实验二离散报告.docx(18页珍藏版)》请在冰点文库上搜索。

实验二离散报告.docx

实验二离散报告

 

实验报告

 

课程名称

离散数学

实验名称

集合上二元关系性质判定的实现

指导单位

计算机科学与技术系

 

实验报告

实验名称

集合上二元关系性质判定的实现

指导教师

实验类型

验证

实验学时

4

实验时间

一、实验目的和要求

内容:

编程实现任意集合上二元关系的性质判定。

要求:

能正确判定任意二元关系的自反性、对称性、传递性、反自反性和反对称性。

二、实验环境(实验设备)

X86计算机

IDE:

CodeBlocks16.01

编译器:

GUNGCC

三、实验原理及内容

输入集合已经集合上面的序偶关系,输出关系满足的性质。

整体思路为将关系转换成矩阵,根据矩阵判断关系的性质。

若矩阵主对角线元素都是1,则满足自反性。

若矩阵主对角线元素都是0,则满足反自反性。

若矩阵所有元素关于主对角线对称,则满足对称性。

若矩阵中出现了关于主对角线对称的元素,则不满足反对称性,否则满足反对称性。

若矩阵的传递闭包等于矩阵自己,则矩阵满足传递性。

为了能够处理集合中含有字母的情况,程序将所有输入当成字符串来处理,然后将每一个字符与矩阵下标进行键值映射,这样,在序偶关系中,通过字符就可以很轻松的找到对应的下标,从而很轻松将序偶关系用矩阵表示。

程序定义的全局变量有:

chara[200];//保存输入的集合A字符串

charR[300];//保存输入的序偶R字符串

mapM;//保存字符与矩阵下标的映射(需#include

intX[200][200];//关系对应的矩阵

intlen;//集合A中含有的元素数量

inttmp[200][200];//求传递闭包过程中,用来保存矩阵的传递闭包

inttmp1[200][200];//求传递闭包过程中,用来保存矩阵的N次方。

第一步:

将集合中的元素与矩阵下标映射

由于集合A中可能含有字母,为了后面能够更加方便的将序偶关系转换成矩阵,第一步先将集合A中所以元素与矩阵下标进行映射,并统计集合A中元素个数。

引用STL库文件#include实现键值映射。

代码为:

intinit()

{

inti=0;

intl=strlen(a);

intj=0;

for(i=0;i

{

if((a[i]>='a'&&a[i]<='z')||(a[i]>='A'&&a[i]<='Z')||(a[i]>='0'&&a[i]<='9'))

{

M[a[i]]=j++;

}

}

returnj;

}

算法复杂度分析:

对输入的字符串进行循环遍历,时间复杂度为O(n)。

 

第二步,将关系转换成矩阵

由于上一步中已经将集合中元素与矩阵下标进行了映射,那定位关系中第一元素和第二元素就可以直接用语句M[R[I]],将关系转换成矩阵也就容易多了,X[M[R[i+1]]][M[R[i+3]]]表示序偶对应的矩阵元素。

代码:

voidsolve()

{

inti,j;

i=j=0;

intl=strlen(R);

while(i

{

if(R[i]=='<')

{

if(find(a,a+strlen(a),R[i+1])==a+strlen(a)||find(a,a+strlen(a),R[i+3])==a+strlen(a))

{

printf("输入有误,关系R中包含非法元素\n");

exit(0);

}

X[M[R[i+1]]][M[R[i+3]]]=1;

i+=5;

}

else

{

i++;

}

}

}

算法复杂度分析:

对输入的序偶字符串进行遍历,时间复杂度是O(n)。

用矩阵进行运算,空间复杂度是O(n^2)。

第三步:

根据矩阵求满足的性质

(1).自反性

如果矩阵中主对角线元素都是1,那么就满足自反性,否则不满足。

判断的时候只要找到第一个对角线元素不是1,就可以断定不满足自反性

代码:

boolJudgeZiFan()

{

inti;

intflag=1;

for(i=0;i

{

if(X[i][i]!

=1)

{

flag=0;

break;

}

}

if(flag)

{

returntrue;

}

else

{

returnfalse;

}

}

算法复杂度分析:

由于只要扫描对角线元素,所以时间复杂度是O(n)。

 

(2)反自反性

如果矩阵中主对角线元素都是0,那么就满足反自反性,否则,就不满足。

判断的时候扫描对角线元素,只要出现1就可断定不满足反自反性。

代码:

boolJudgeFanZiFan()

{

for(inti=0;i

{

if(X[i][i]>0)

{

returnfalse;

}

}

returntrue;

}

(3)对称性

如果对矩阵中,每一个X[i][j],都有M[j][i]=1,那么就满足对称性,否则,不满足对称性。

若出现X[i][j]==1&&X[j][i]==0,就可以断定不满足对称性。

判断的时候只要扫描上三角矩阵即可。

boolJudgeDuiCheng()

{

inti,j;

for(i=0;i

{

for(j=0;j

{

if(X[i][j])

{

if(X[j][i]!

=1)

{

returnfalse;

}

}

}

}

returntrue;

}

算法复杂度分析:

扫描上三角矩阵,时间复杂度是O(n^2)。

(4)反对称性

如果矩阵中出现了关于主对角线对称的元素,那么就不满足反对称性,否则,满足反对称性。

判断的时候只要出现了X[i][j]==1&&X[j][i]==1就可以断定不满足反对称性。

判断的时候也只要扫描上三角矩阵。

代码:

boolJudgeFanDuiCheng()

{

for(inti=0;i

{

for(intj=i+1;j

{

if(X[i][j])

{

if(X[j][i])

{

returnfalse;

}

}

}

}

returntrue;

}

算法复杂度分析:

扫描上三角矩阵,时间复杂度是O(n^2)

 

(5).传递性

如果矩阵的传递闭包等于矩阵自己,那么就满足传递性,否则不满足。

求矩阵的传递闭包首先定义一个求矩阵的幂的运算,这个地方只要求矩阵和X矩阵相乘就可以。

还要定义一个特殊的求矩阵相加的运算,如果相加后矩阵元素大于1,就把元素置为1.最后只要比较一下传递闭包是不是与X相等就行了。

具体步骤是先定义两个全局数组tmp[][],和tmp1[][],首先初始化为X矩阵。

tmp1用来累计和矩阵X的乘积,每次都和X相乘一次tmp1的幂就增加1,然后将tmp1与tmp矩阵相加(元素大于1就置成1),如此循环。

函数cal()为tmp1与X相乘,函数combine为tmp1与tmp相加。

代码:

boolJudgeChuanDi()

{

inti,j;

for(i=0;i

{

for(j=0;j

{

tmp[i][j]=X[i][j];

tmp1[i][j]=X[i][j];

}

}

for(i=2;i<=len;i++)

{

cal();

combine();

}

for(inti=0;i

{

for(intj=0;j

{

if(tmp[i][j]!

=X[i][j])

{

returnfalse;

}

}

}

returntrue;

}

求矩阵的幂的运算:

首先0将X矩阵拷贝到tmp1[200][200],然后每次都将tmp1与X相乘

代码:

voidcal()

{

intxtmp[200][200];

intk,p;

for(inti=0;i

{

for(intj=0;j

{

intsum=0;

for(k=0;k

{

sum+=tmp1[i][k]*X[k][j];

}

if(sum==0)

{

xtmp[i][j]=0;

}

else

{

xtmp[i][j]=1;

}

}

}

for(inti=0;i

{

for(intj=0;j

{

tmp1[i][j]=xtmp[i][j];

}

}

}

矩阵相加的运算:

如果相加后元素大于1,就置为1

代码:

voidcombine()

{

for(inti=0;i

{

for(intj=0;j

{

if(tmp1[i][j]||tmp[i][j])

{

tmp[i][j]=1;

}

}

}

}

算法复杂度分析:

主函数中,初始化tmp和tmp1时间复杂度是O(n^2)。

调用循环len-1次,然后每次cal函数进行矩阵相乘的复杂度是O(n^3),combine进行矩阵相加是O(n^2)。

这个运算步骤的时间复杂度是O(n^4),最后将tmp与X比较的时间复杂度是O(n^2)。

综上,时间复杂度是O(n^4)。

空间复杂度分析:

由于定义了两个临时数组tmp[]和tmp1[][],每一个是O(n^2),所以,空间复杂度是O(n^2)。

主函数进行数据的读入,输出,以及函数的调用

Main函数代码:

intmain()

{

memset(tmp,0,sizeof(tmp));

memset(tmp1,0,sizeof(tmp1));

memset(a,0,sizeof(a));

memset(R,0,sizeof(R));

printf("请输入集合A,以逗号隔开各元素,回车结束\n");

gets(a);

len=init();

printf("请输入关系R,格式,......回车结束\n");

gets(R);

solve();

boolZiFan=JudgeZiFan();

boolDuiCheng=JudgeDuiCheng();

boolChuanDi=JudgeChuanDi();

boolFanZiFan=JudgeFanZiFan();

boolFanDuiCheng=JudgeFanDuiCheng();

printf("性质为:

\n");

if(ZiFan)

{

printf("自反性\n");

}

if(FanZiFan)

{

printf("反自反性\n");

}

if(DuiCheng)

{

printf("对称性\n");

}

if(FanDuiCheng)

{

printf("反对称性\n");

}

if(ChuanDi)

{

printf("传递性\n");

}

return0;

}

程序测试:

案例一:

课本112页例题5

输入集合为1,2,3,4

关系为<1,1>,<1,3>,<2,2>,<3,3>,<3,1>,<3,4>,<4,3>,<4,4>

结果正确。

 

案例二:

输入集合为a,b,c

输入关系为,,

结果正确。

 

案例三:

课本131页例题1

输入集合:

1,2,3,4

输入关系:

<1,1>,<1,4>,<4,1>,<4,4>,<2,2>,<2,3>,<3,2>,<3,3>

结果正确

 

案例四:

输入集合a,b,c,d

输入关系:

,,,

结果正确

 

案例五:

程序容错性测试

结果正确

四、实验小结(包括问题和解决方法、心得体会、意见与建议等)

1.个人感觉这个程序的难点是传递性的判断,因为要求传递闭包,涉及到矩阵的乘法和加法,矩阵相乘在循环的时候,循环变量要弄清楚,容易出错。

2.这个程序只能处理小批量数据,最多将矩阵行列改成几千,处理包含几千元素的集合。

对于包含上万元素的集合的数据,如果还用二维数据,会爆栈,应该改为三元组表示的稀疏矩阵

3.程序的容错性。

如果不按照提示的规则输入,比如多几个空格标点,程序能恰当处理,如果关系中出现了集合以外的元素,程序能判断并提示。

但是关系一定要以的形式出现,否则程序将不能识别,导致结果出错。

五、指导教师评语

成绩

批阅人

日期

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 解决方案 > 学习计划

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2