c++实现关系的运算 1、关系的幂运算 2、关系的闭包运算

c++实现关系的运算 1、关系的幂运算 2、关系的闭包运算,第1张

matrix operator(matrix tem) //重载 号

{

matrix ans;

anssize = size;

ansclear();

for(int i = 0; i <= size; ++i)

for(int j = 0; j <= size; ++j)

if (m[i][j])

{

for(int k = 0; k <= size ; ++k)

ansm[i][k] += m[i][j]temm[j][k];

}

return ans;

}

//ans 初始化为单位矩阵 tem 为 原矩阵 m为幂指数

while(m)

{

if (m&1) ans = anstem;

tem = temtem;

m >>= 1;

}

2

}

// 求 传递闭包

for(j = 0; j < 10; j++ )

{

for(i = 0 ;i < 10; i++ )

if (map[i][j])

{

for(k = 0; k < 10; k++)

map[i][k] |= map[j][k];

}

}

课本上是这么说的:

设R是A上的二元关系,R的自反(对称、传递)闭包是关系R',使

1R'是自反(对、传)的;

2R'包含R;

3对任何自反(对、传)的关系R'',如果R''包含R,那么R''包含R'。

我们的老师说,自反闭包就是在原关系中加一些序偶对,使其满足自反性,这样得到的新序偶集合就是自反闭包。对,传类似自反。

就这些了,希望能帮你理解它。

在复杂的逻辑下 JavaScript 需要被模块化 模块需要封装起来 只留下供外界调用的接口 闭包是 JavaScript 中实现模块封装的关键 也是很多初学者难以理解的要点  

虽然 JavaScript 天生就是一副随随便便的样子 但是随着浏览器能够完成的事情越来越多 这门语言也也越来越经常地摆出正襟危坐的架势 在复杂的逻辑下 JavaScript 需要被模块化 模块需要封装起来 只留下供外界调用的接口 闭包是 JavaScript 中实现模块封装的关键 也是很多初学者难以理解的要点 最初 我也陷入迷惑之中 现在 我自信对这个概念已经有了比较深入的理解 为了便于理解 文中试图 封装一个比较简单的对象

我们试图在页面上维护一个计数器对象 ticker 这个对象维护一个数值 n 随着用户的 *** 作 我们可以增加一次计数(将数值 n 加上 ) 但不能减少 n 或直接改变 n 而且 我们需要时不时查询这个数值

门户大开的 JSON 风格模块化

一种门户大开的方式是

复制代码 代码如下: var ticker = {     n:     tick:function(){         this n++;     } };

这种方式书写自然 而且确实有效 我们需要增加一次计数时 就调用 ticker tick() 方法 需要查询次数时 就访问 ticker n 变量 但是其缺点也是显而易见的 模块的使用者被允许自由地改变 n 比如调用 ticker n 或者 ticker n= 我们并没有对 ticker 进行封装 n 和 tick() 看上去是 ticker 的“成员” 但是它们的可访问性和 ticker 一样 都是全局性的(如果 ticker 是全局变量的话) 在封装性上 这种模块化的方式比下面这种更加可笑的方式 只好那么一点点(虽然对有些简单的应用来说 这一点点也足够了)

复制代码 代码如下: var ticker = {}; var tickerN = ; var tickerTick = function(){     tickerN++; }

tickerTick();

值得注意的是 在 tick() 中 我访问的是 this n ——这并不是因为 n 是 ticker 的成员 而是因为调用 tick() 的是 ticker 事实上这里写成 ticker n 会更好 因为如果调用 tick() 的不是 ticker 而是其他什么东西 比如

复制代码 代码如下: var func = ticker tick; func();

这时 调用 tick() 的其实是 window 而函数执行时会试图访问 window n 而出错

事实上 这种“门户大开”型的模块化方式 往往用来组织 JSON 风格的数据 而不是程序 比如 我们可以将下面这个 JSON 对象传给 ticker 的某个函数 来确定 ticker 从 开始计数 每次递进

复制代码 代码如下: var config = {     nStart:     step: }

作用域链和闭包 来看下面的代码 注意我们已经实现了传入 config 对 ticker 进行自定义

复制代码 代码如下: function ticker(config){     var n = config nStart;     function tick(){         n += config step;     } } console log(ticker n); // >undefined

你也许会疑惑 怎么 ticker 从对象变成了函数了?这是因为 JavaScript 中只有函数具有作用域 从函数体外无法访问函数内部的变量 ticker() 外访问 ticker n 获得 undefined 而 tick() 内访问 n 却没有问题 从 tick() 到 ticker() 再到全局 这就是 JavaScript 中的“作用域链”

可是还有问题 那就是——怎么调用 tick() ? ticker() 的作用域将 tick() 也掩盖了起来 解决方法有两种

• )将需要调用方法作为返回值 正如我们将递增 n 的方法作为 ticker() 的返回值 • )设定外层作用域的变量 正如我们在 ticker() 中设置 getN

复制代码 代码如下: var getN; function ticker(config){     var n = config nStart;     getN = function(){         return n;     };     return function(){         n += config step;     }; }

var tick = ticker({nStart: step: }); tick(); console log(getN()); // >

请看 这时 变量 n 就处在“闭包”之中 在 ticker() 外部无法直接访问它 但是却可以通过两个方法来观察或 *** 纵它

在本节第一段代码中 ticker() 方法执行之后 n 和 tick() 就被销毁了 直到下一次调用该函数时再创建 但是在第二段代码中 ticker() 执行之后 n 不会被销毁 因为 tick() 和 getN() 可能访问它或改变它 浏览器会负责维持n 我对“闭包”的理解就是 用以保证 n 这种处在函数作用域内 函数执行结束后仍需维持 可能被通过其他方式访问的变量 不被销毁的机制

可是 我还是觉得不大对劲?如果我需要维持两个具有相同功能的对象 ticker 和 ticker 那该怎么办? ticker() 只有一个 总不能再写一遍吧?

new 运算符与构造函数 如果通过 new 运算符调用一个函数 就会创建一个新的对象 并使用该对象调用这个函数 在我的理解中 下面的代码中 t 和 t 的构造过程是一样的

复制代码 代码如下: function myClass(){} var t = new myClass(); var t = {}; t func = myClass; t func(); t func = undefined;

t 和 t 都是新构造的对象 myClass() 就是构造函数了 类似的 ticker() 可以重新写成

复制代码 代码如下: function TICKER(config){     var n = config nStart;     this getN = function(){         return n;     };     this tick = function(){         n += config step;     } }

var ticker = new TICKER({nStart: step: }); ticker tick(); console log(ticker getN()); // > var ticker = new TICKER({nStart: step: }); ticker tick(); ticker tick(); console log(ticker getN()); // >

习惯上 构造函数采用大写 注意 TICKER() 仍然是个函数 而不是个纯粹的对象(之所以说“纯粹” 是因为函数实际上也是对象 TICKER() 是函数对象) 闭包依旧有效 我们无法访问 ticker n

原型 prototype 与继承 上面这个 TICKER() 还是有缺陷 那就是 ticker tick() 和 ticker tick() 是互相独立的!请看 每使用 new 运算符调用 TICKER() 就会生成一个新的对象并生成一个新的函数绑定在这个新的对象上 每构造一个新的对象 浏览器就要开辟一块空间 存储 tick() 本身和 tick() 中的变量 这不是我们所期望的 我们期望 ticker tick 和 ticker tick 指向同一个函数对象

这就需要引入原型

JavaScript 中 除了 Object 对象 其他对象都有一个 prototype 属性 这个属性指向另一个对象 这“另一个对象”依旧有其原型对象 并形成原型链 最终指向 Object 对象 在某个对象上调用某方法时 如果发现这个对象没有指定的方法 那就在原型链上一次查找这个方法 直到 Object 对象

函数也是对象 因此函数也有原型对象 当一个函数被声明出来时(也就是当函数对象被定义出来时) 就会生成一个新的对象 这个对象的 prototype 属性指向 Object 对象 而且这个对象的 constructor 属性指向函数对象

通过构造函数构造出的新对象 其原型指向构造函数的原型对象 所以我们可以在构造函数的原型对象上添加函数 这些函数就不是依赖于 ticker 或 ticker 而是依赖于 TICKER 了

你也许会这样做

复制代码 代码如下: function TICKER(config){     var n = config nStart; } TICKER prototype getN = function{     // attention : invalid implementation     return n; }; TICKER prototype tick = function{     // attention : invalid implementation     n += config step; };

请注意 这是无效的实现 因为原型对象的方法不能访问闭包中的内容 也就是变量 n TICK() 方法运行之后无法再访问到 n 浏览器会将 n 销毁 为了访问闭包中的内容 对象必须有一些简洁的依赖于实例的方法 来访问闭包中的内容 然后在其 prototype 上定义复杂的公有方法来实现逻辑 实际上 例子中的 tick() 方法就已经足够简洁了 我们还是把它放回到 TICKER 中吧 下面实现一个复杂些的方法 tickTimes() 它将允许调用者指定调用 tick() 的次数

复制代码 代码如下: function TICKER(config){     var n = config nStart;     this getN = function(){         return n;     };     this tick = function(){         n += config step;     }; } TICKER prototype tickTimes = function(n){     while(n> ){         this tick();         n ;     } }; var ticker = new TICKER({nStart: step: }); ticker tick(); console log(ticker getN()); // > var ticker = new TICKER({nStart: step: }); ticker tickTimes( ); console log(ticker getN()); // >

这个 TICKER 就很好了 它封装了 n 从对象外部无法直接改变它 而复杂的函数 tickTimes() 被定义在原型上 这个函数通过调用实例的小函数来 *** 作对象中的数据

所以 为了维持对象的封装性 我的建议是 将对数据的 *** 作解耦为尽可能小的单元函数 在构造函数中定义为依赖于实例的(很多地方也称之为“私有”的) 而将复杂的逻辑实现在原型上(即“公有”的)

最后再说一些关于继承的话 实际上 当我们在原型上定义函数时 我们就已经用到了继承! JavaScript 中的继承比 C++ 中的更……呃……简单 或者说简陋 在 C++ 中 我们可能会定义一个 animal 类表示动物 然后再定义 bird 类继承 animal 类表示鸟类 但我想讨论的不是这样的继承(虽然这样的继承在 JavaScript 中也可以实现) 我想讨论的继承在 C++ 中将是 定义一个 animal 类 然后实例化了一个 myAnimal 对象 对 这在 C++ 里就是实例化 但在 JavaScript 中是作为继承来对待的

JavaScript 并不支持类 浏览器只管当前有哪些对象 而不会额外费心思地去管 这些对象是什么 class 的 应该具有怎样的结构 在我们的例子中 TICKER() 是个函数对象 我们可以对其赋值(TICKER= ) 将其删掉(TICKER=undefined) 但是正因为当前有 ticker 和 ticker 两个对象是通过 new 运算符调用它而来的 TICKER() 就充当了构造函数的作用 而 TICKER prototype 对象 也就充当了类的作用

lishixinzhi/Article/program/Java/JSP/201311/20429

第一个程序

集合的交并差运算

#include<stdioh>

#include<stdlibh>

typedef struct pointer{

char dat;

struct pointer link;

} pointer;

void readdata(pointer head){ //读集合

pointer p;

char tmp;

printf("input data ('0' for end):");

scanf("%c",&tmp);

while(tmp!='0')

{

if((tmp<'a')||(tmp>'z'))

{

printf("输入错误!必须为小写字母!\n");

return;

}

p=(pointer )malloc(sizeof(struct pointer));

p->dat=tmp;

p->link=head->link;

head->link=p;

scanf("%c",&tmp);

}

}

void disp(pointer head){ //显示集合数据

pointer p;

p=head->link;

while(p!=NULL)

{

printf("%c ",p->dat);

p=p->link;

}

printf("\n");

}

void bing(pointer head1,pointer head2, pointer head3){ //计算集合1与集合2的并

pointer p1,p2,p3;

p1=head1->link;

while(p1!=NULL)

{

p3=(pointer )malloc(sizeof(struct pointer));

p3->dat=p1->dat;

p3->link=head3->link;

head3->link=p3;

p1=p1->link;

}

p2=head2->link;

while(p2!=NULL)

{

p1=head1->link;

while((p1!=NULL)&&(p1->dat!=p2->dat))

p1=p1->link;

if(p1==NULL)

{

p3=(pointer )malloc(sizeof(struct pointer));

p3->dat=p2->dat;

p3->link=head3->link;

head3->link=p3;

}

p2=p2->link;

}

}

void jiao(pointer head1,pointer head2, pointer head3){ //计算集合1与集合2的交

pointer p1,p2,p3;

p1=head1->link;

while(p1!=NULL)

{

p2=head2->link;

while((p2!=NULL)&&(p2->dat!=p1->dat))

p2=p2->link;

if((p2!=NULL)&&(p2->dat=p1->dat))

{

p3=(pointer )malloc(sizeof(struct pointer));

p3->dat=p1->dat;

p3->link=head3->link;

head3->link=p3;

}

p1=p1->link;

}

}

void cha(pointer head1,pointer head2, pointer head3){ //计算集合1与集合2的差

pointer p1,p2,p3;

p1=head1->link;

while(p1!=NULL)

{

p2=head2->link;

while((p2!=NULL)&&(p2->dat!=p1->dat))

p2=p2->link;

if(p2==NULL)

{

p3=(pointer )malloc(sizeof(struct pointer));

p3->dat=p1->dat;

p3->link=head3->link;

head3->link=p3;

}

p1=p1->link;

}

}

main(){

pointer head1,head2,head3;

head1=(pointer )malloc(sizeof(struct pointer));

head1->link=NULL;

head2=(pointer )malloc(sizeof(struct pointer));

head2->link=NULL;

head3=(pointer )malloc(sizeof(struct pointer));

head3->link=NULL;

printf("输入集合1:\n");

readdata(head1);

printf("输入集合2:\n");

readdata(head2);

printf("集合1为:\n");

disp(head1);

printf("集合2为:\n");

disp(head2);

printf("集合1与集合2的并为:\n");

bing(head1,head2,head3);

disp(head3);

head3->link=NULL;

printf("集合1与集合2的交为:\n");

jiao(head1,head2,head3);

disp(head3);

head3->link=NULL;

printf("集合1与集合2的差为:\n");

cha(head1,head2,head3);

disp(head3);

}

测试用例为(0表示集合输入结束):

fdsa0

savc0

第二个程序

计算关系的闭包(3种)

#include<stdioh>

void output(int s[][100]);

void zifan(int s2[][100]);

void duichen(int s2[][100]);

void chuandi2(int s2[][100]);

void chuandi1(int s2[][100]);

void aa();

int s[100][100],z;

int d,n ,i,j;

int main(){aa();return 0;}

void aa()

{

printf("请输入矩阵的行数(必须小于10)\n ");

scanf("%d",&n);

printf("请输入矩阵的列数(必须小于10)\n ");

scanf("%d",&d);

printf("请输入关系矩阵\n");

for(i=0;i<n;i++)

{ printf("\n");

printf("请输入矩阵的第%d行元素",i);

for(j=0;j<d;j++)

scanf("%d",&s[i][j]);

}

printf("输入对应序号选择算法\n1:自反闭包\n2:传递闭包1\n3:传递闭包(Warhall算法)2\n4:对称闭包\n");

scanf("%d",&z);

switch(z)

{

case 1:zifan(s); break;

case 2:chuandi1(s);break;

case 3:chuandi2(s);break;

case 4:duichen(s); break;

}

}

void output(int s[][100])

{printf("所求关系矩阵为\n");

for(i=0;i<n;i++)

{for(j=0;j<d;j++)

printf("%d",s[i][j]);

printf("\n");

}

}

void zifan(int s2[][100])

{

for(i=0;i<n;i++)

s2[i][i]=1;

output(s2);aa();

}

void duichen(int s2[][100])

{int s1[100][100];

for(i=0;i<n;i++)

for(j=0;j<d;j++)

s1[j][i]=s2[i][j];

for(i=0;i<n;i++)

for(j=0;j<d;j++)

{s2[i][j]=s2[i][j]+s1[i][j];

if(s2[i][j]>1)

s2[i][j]=1;

}

output(s2);

aa();

}

void chuandi1(int s2[][100])

{int m[100][100],a[100][100],k,h;

int t[100][100];

for(i=0;i<n;i++)

for(j=0;j<d;j++)

{ a[i][j]=0;

t[i][j]=s2[i][j];

m[i][j]=s2[i][j];}

for(h=0;h<n;h++)

{for(i=0;i<n;i++)

for(j=0;j<d;j++)

if(m[i][j]==1)

{for(k=0;k<n;k++)

if(s2[j][k]==1)

a[i][k]=1;

}

for(i=0;i<n;i++)

for(j=0;j<d;j++)

{ m[i][j]=a[i][j];

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

a[i][j]=0;

if(t[i][j]>1)

t[i][j]=1;

}

}

output(t);aa();

}

void chuandi2(int s2[][100])

{int k;

for(i=0;i<n;i++)

for(j=0;j<n;j++)

if(s2[j][i]==1)

for(k=0;k<n;k++)

s2[j][k]+=s2[i][k];

for(i=0;i<n;i++)

for(j=0;j<n;j++)

if(s2[i][j]>1)

s2[i][j]=1;

output(s2);aa();

}

将原关系R矩阵的主对角线的元素全化为1即可。

补充:

在离散数学中,对于既不是自反也不是反自反的关系,适当的添加一些序偶使之变成自反关系,同时要求添加的序偶尽可能的少。添加序偶后的关系称为原关系的自反闭包,记为r(R)。

例题:

令A={1,2,3}、R={<1,1>,<2,2>},求R的自反闭包。

解:由于R缺少序偶<3,3>,R不是自反关系,添加该序偶后则变成自反关系(即,在关系矩阵中,对角线上的数字均为1)。所以R的自反闭包r(R)={<1,1>,<2,2>,<3,3>}。

由求自反闭包的过程可以得到:r(R)=RUIA

一个关系不具有自反, 对称, 传递这3种基本性质之一,但均可以通过对该关系的扩充(在关系中增添序偶),使扩充后的关系具有这种性质,这种包含该关系的最小扩充称为该关系关于这种性质的闭包下面给出闭包的定义

设R是X上的关系,R的自反(对称,传递)闭包R1是这样的包含R(或R包含于R1)的自反(对称,传递)关系,对任意的自反(对称,传递) 关系S,如果R包含于S,则必有R1包含于S

关系闭包在数学中,在日常生活中均有广泛的应用,比如在数学中,小于(<)或大于(>)关系均没有自反性,但它们的的自反闭包是小于等于(≤)或大于等于((≥),却有自反性,在数学中经常要用到小于关系表示量之间的关系,但是有时感到用小于关系不方便,而用小于等于关系,实际上是将量之间的关系进行扩大,不自觉地用了小于的自反闭包,日常生活中我们按同龄或同班或同乡关系将人分组,一般来说同龄,同班,同乡关系指两个不同的人之间的一种关系,这种关系就不具有自反性,如果我们约定了自已与自已同龄,同班,同乡,此时它们就有了自反性,如果仅有一个人和其他人年龄均不同,此时他自已就可构成一组。

小于关系是不对称,它的逆关系大于关系也是不对称,但将两者关系并起来(将关系看成集合),得不等关系却是的对称的,不等关系是小于或大于关系的对称闭包,夫对妻的关系是不对称的,妻对夫的关系也是不对称的,但对称闭包婚姻关系却是对称的(考虑到男女平等,即对称性)。大于1的关系是不传递的,大于2的关系也是不传递的,…将大于1,大于2,大于3,…全部并起来得到大于关系却是传递的,大于关系是大于1的关系的传递闭包,父子关系是不传递的,但它的传递闭包是长辈对后辈关系却是传递的。

总而言之,我们经常不自觉的用到了关系闭包的概念,在数学中随着人们的对关系的深入认识,自觉地使用闭包的概念,比如在数学中严格偏序关系的自反闭包是偏序关系,偏序集利用所谓盖住关系的关系图(哈斯图),来描述该偏序集十分简单明了,盖住关系的自反传递闭包就是偏序集上的偏序关系。

以上就是关于c++实现关系的运算 1、关系的幂运算 2、关系的闭包运算全部的内容,包括:c++实现关系的运算 1、关系的幂运算 2、关系的闭包运算、什么是闭包 离散数学、JavaScript的模块化:封装(闭包),继承(原型) 介绍等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://www.54852.com/zz/9767987.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-01
下一篇2023-05-01

发表评论

登录后才能评论

评论列表(0条)

    保存