ISM.h
#define M 12 //当改变M的值的时候,在编译之前请做一下工作Build -> Clean清除掉原来的编译文件,然后重新编译文件 //这样就不会出现内存报错的现象了。 typedef struct Node { int count; int a[M]; }JHRA; class ISM { private: int array1[M][M]; //有向图的关系矩阵 int array2[M][M]; //(A+E)的k次方的存放结果 int Earray[M][M];//单位矩阵 int AEarray[M][M]; JHRA JHR[M],JHA[M],pC[M]; int SRMax; //输入的最大值 public: ISM(); //矩阵的初始化 void CreateAvailableArray(); //求有向图的邻接矩阵矩阵 void print(); //输出矩阵 void GetAvailableArray(); //得到可达矩阵 void MutiArray(int A[][M],int B[][M]); //矩阵乘法 void FZArray(int A[][M],int B[][M]); //矩阵赋值 int XDArray(int A[][M],int B[][M]); //矩阵是否相等 void JFArray(int A[][M],int B[][M]); //矩阵加法 ///////////////////////////////////////////////////////////////////////////// //由可达矩阵求出层级有向图 void CJGraplic(); //基于可达矩阵求出层级有向图 void SCElement(JHRA pC[M],int a[],int flag); //删除一个元素 int JHQD(int a[],int b[],int count); //集合是否相等 }; // 无分号时error C2143: syntax error : missing ';' before 'PCH creation point'
ISM.cpp
#include <stdio.h> #include <stdlib.h> #include "ISM.H" ISM::ISM() { for(int i=0;i<M;i++) { JHR[i].count=0; JHA[i].count=0; pC[i].count=0; for(int j=0;j<M;j++) { array1[i][j]=0; array2[i][j]=0; AEarray[i][j]=0; JHR[i].a[j]=0; JHA[i].a[j]=0; pC[i].a[j]=0; SRMax=0; if(i==j) Earray[i][j]=1; else Earray[i][j]=0; } } } void ISM::CreateAvailableArray() { int a=0,b=0; printf("请输入矩阵的维数/n"); scanf("%d",&SRMax); if(SRMax>M) { printf("你输入的维数大于程序规定的维数,请到ISM.h文件中的#define M 12,改变M的值" "当改变M的值的时候,在编译之前请做一下工作Build -> Clean清除掉原来的编译文件,然后" "重新编译文件。/n" "由于程序给你带来的不便,敬请原谅!/n"); exit(0); } printf("请输入相关联的顶点,以0,0'结束/n"); while(1) { int Max=0; scanf("%d,%d",&a,&b); //Max=(a>b ? a:b)>Max ? (a>b ? a:b): Max; Max=a>b ? a:b;//每次只需要判断这次输入的最大值是否大于SRMax,而不需要把这个输入过程的最大值来判断 if(0==a) break; if(Max>SRMax) { printf("请仔细输入,您刚才的输入有误!/n"); continue;//此处要continue,因为要重新输入,要有容错能力 } if(SRMax<=M) array1[a-1][b-1]=1; else printf("你输入的矩阵维数过大,请重新输入"); } printf("所建立的可达矩阵为:/n"); GetAvailableArray(); } void ISM::GetAvailableArray() //得到可达矩阵 { printf("打印原始邻接矩阵矩阵array1/n"); for(int i=0;i<SRMax;i++) { for(int j=0;j<SRMax;j++) { printf(" %d ",array1[i][j]); } printf("/n"); } printf("/n"); printf("打印单位矩阵Earray/n"); for(i=0;i<SRMax;i++) { for(int j=0;j<SRMax;j++) { printf(" %d ",Earray[i][j]); } printf("/n"); } printf("/n"); JFArray(array1,Earray); //邻接矩阵与单位矩阵的加法 FZArray(AEarray,array1); //矩阵赋值 printf("打印AEarray/n"); for(i=0;i<SRMax;i++) { for(int j=0;j<SRMax;j++) { printf(" %d ",AEarray[i][j]); } printf("/n"); } while((XDArray(array1,array2))==0) //矩阵是否相等,为0则不相等 { MutiArray(array1,AEarray); //矩阵乘法(A+E)的K次方 } printf("故可达矩阵为:/n"); print(); } void ISM::print() { for(int i=0;i<SRMax;i++) { for(int j=0;j<SRMax;j++) printf("%d ",array1[i][j]); printf("/n"); } } void ISM::MutiArray(int A[][M],int B[][M]) //矩阵乘法 //此处不是简单的矩阵乘法,而是布尔矩阵乘法 { //int a=ISM::Max; static int count=0; FZArray(array2,A); //矩阵赋值 int C[M][M]={0}; for(int i=0;i<SRMax;i++) for(int j=0;j<SRMax;j++) for(int k=0;k<SRMax;k++) { int t=0; t=A[i][k]<=B[k][j] ? A[i][k]:B[k][j];//A[i][j]与B[i][j]相乘,取二者中的较小的值 C[i][j] =C[i][j]>=t ? C[i][j]:t; } count++; FZArray(A,C); //矩阵赋值 printf("这是(A+E)的第 %d 次乘方/n",count); print(); } void ISM::JFArray(int A[][M],int B[][M]) //矩阵加法 //此处不是简单的矩阵加法,而是布尔矩阵加法 { for(int i=0;i<SRMax;i++) for(int j=0;j<SRMax;j++) A[i][j]=A[i][j]>B[i][j] ? A[i][j]:B[i][j]; } void ISM::FZArray(int A[][M],int B[][M]) //矩阵赋值 { for(int i=0;i<SRMax;i++) for(int j=0;j<SRMax;j++) A[i][j]=B[i][j]; } int ISM::XDArray(int A[][M],int B[][M]) //矩阵是否相等 { for(int i=0;i<SRMax;i++) for(int j=0;j<SRMax;j++) if(A[i][j]!=B[i][j]) { return 0; break; } return 1; } /////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// void ISM::CJGraplic() //基于可达矩阵求出层级有向图 { //////////////////////////////////求可达矩阵和先行矩阵////////////////////////////////////////////////// for(int i=0;i<SRMax;i++) { int t=0; for(int j=0;j<SRMax;j++) { if(array1[i][j]==1) { JHR[i].count +=1 ; JHR[i].a[t++]=j+1; } } } for(i=0;i<SRMax;i++) { int t=0; for(int j=0;j<SRMax;j++) { if(array1[j][i]==1) { JHA[i].count +=1 ; JHA[i].a[t++]=j+1; } } } //字符串匹配算法 printf("打印JHR【】与JHA【】集合/n"); for(i=0;i<SRMax;i++) { printf("可达矩阵的元素个数:%d; 先行矩阵的元素个数:%d/n",JHR[i].count,JHA[i].count); printf("%d的可达集合JHR[]:",i+1); for(int j=0;j<JHR[i].count;j++) printf(" %d ",JHR[i].a[j]); printf(" %d的先行集合JHA[]:",i+1); for(j=0;j<JHA[i].count;j++) printf(" %d ",JHA[i].a[j]); printf("/n/n"); } //////////////////求可达矩阵JHR【】与先行矩阵JHA【】的交集存放在Pc中//////////////////////////////////////////////////////////// printf("求可达矩阵JHR【】与先行矩阵JHA【】的交集存放在Pc中/n"); int k=0; while(k<SRMax) { int t=0; int n=JHR[k].count>JHA[k].count ? JHR[k].count : JHA[k].count ; for(int i=0;i<n;i++) for(int j=0;j<JHA[k].count;j++) if(JHR[k].a[i]==JHA[k].a[j]) { pC[k].count++; pC[k].a[t++]=JHR[k].a[i]; } k++; } for(i=0;i<SRMax;i++) { printf("%d 的可达矩阵JHR与先行矩阵JHA的交集存放在Pc中/n",i+1); printf("交集pC【】中的元素的个数为%d:",pC[i].count); for(int j=0;j<pC[i].count;j++) { printf(" %d ",pC[i].a[j]); } printf("/n/n"); } ///////////////////////////////////////////求可达矩阵的有向图/////////////////////////////////////////////// /* for(int j=0;j<SRMax;j++) for(i=0;i<SRMax;i++) { static int CJS=1; //层级数 int jhxd; //如果集合相等,则jhxd表示集合的元素个数 if(JHR[i].count==pC[i].count && pC[i].count != 0) { jhxd=JHQD(JHR[i].a,pC[i].a,pC[i].count); //集合是否相等 if(jhxd!=0) { for(int j=0;j<JHR[i].count;j++) printf(" %d ",JHR[i].a[j]); printf("的级数为 %d /n",CJS); CJS++; SCElement(pC,pC[i].a,jhxd); //删除一个元素或一组元素 } } } } */ /* for(int j=0;j<SRMax;j++) for(i=0;i<SRMax;i++) { int flag=0; static int CJS=1; //层级数 int jhxd; //如果集合相等,则jhxd表示集合的元素个数 //原来只考虑到了两个集合中相等并且集合中的元素不止一个的情况,遗漏了下面的情况: //对于有四个集合其中两个相等,另外两个也相等,故他们的等级也应该相等 for(int t=i;t<SRMax;t++) if(JHR[t].count==pC[t].count && pC[t].count != 0) { jhxd=JHQD(JHR[t].a,pC[t].a,pC[t].count); //集合是否相等 if(jhxd!=0) { for(int j=0;j<JHR[t].count;j++) printf(" %d ",JHR[t].a[j]); flag++; printf("的级数为 %d /n",CJS); //CJS++; SCElement(pC,pC[t].a,jhxd); //删除一个元素或一组元素 } } if(flag!=0) CJS++; } } //为什么会出错呢?因为找到相等结合就删除,删除一个元素或删除一组元素之后必然会生成一组集合相等 //而这两组集合等级并不相同,如果不删除有两组集合相等,那么这两组集合等级相等 //解决之道是:想找出一个循环中所有的几组相等的集合,然后再删除,不能边找边删。 */ for(int j=0;j<SRMax;j++) for(i=0;i<SRMax;i++) { struct node { int a; //存放是哪个集合 int YScount; //存放该集合的元素个数 }; struct JH { int JHxdCount; //集合相等的组数 struct node pD[M]; }; struct JH pE={0,0,0}; int flag=0,t3=0; static int CJS=1; //层级数 int jhxd; //如果集合相等,则jhxd表示集合的元素个数 //原来只考虑到了两个集合中相等并且集合中的元素不止一个的情况,遗漏了下面的情况: //对于有四个集合其中两个相等,另外两个也相等,故他们的等级也应该相等 for(int t=i;t<SRMax;t++) if(JHR[t].count==pC[t].count && pC[t].count != 0) { jhxd=JHQD(JHR[t].a,pC[t].a,pC[t].count); //集合是否相等 if(jhxd!=0) { for(int j=0;j<JHR[t].count;j++) printf(" %d ",JHR[t].a[j]); flag++; printf("的级数为 %d /n",CJS); pE.pD[t3].a=t; pE.pD[t3].YScount=jhxd; pE.JHxdCount++; t3++; //CJS++; //SCElement(pC,pC[t].a,jhxd); //删除一个元素或一组元素 } } for(t=0;t<pE.JHxdCount;t++) { int i=pE.pD[t].a; SCElement(pC,pC[i].a,pC[i].count); //删除一个元素或一组元素 } if(flag!=0) CJS++; } } //为什么最后要加一个外循环? 因为如果不加的话,可能第一次或前几次就循环到i=SRMax;而级数并没有判断完 //故加了一个外循环for(int j=0;j<SRMax;j++),你可以不不加看看所得的结果? void ISM::SCElement(JHRA pC[M],int b[],int flag) //删除一个元素或一组元素,flag为删除元素的个数 { //删除集合b中元素在pC和JHR中所对应的元素 for(int i=0;i<SRMax;i++) { int t2=0; int t=JHR[i].count; for(int j=0;j<t;j++) if(JHR[i].a[j]==b[t2] && t2<flag) { if(t2==flag-1) { for(int n=j;n<t;n++) { if(n+1==t) break; //JHR[i].a[n]=JHR[i].a[n+1]; JHR[i].a[n+1-flag]=JHR[i].a[n+1]; } } JHR[i].count--; t2++; if(JHR[i].count==0) break; } printf("输出删除后的集合元素的个数:%d ",JHR[i].count); printf("输出删除后的集合JHR[%d]: ",i); for(j=0;j<JHR[i].count;j++) printf(" %d ",JHR[i].a[j]); printf("/n/n"); /* int t1=pC[i].count; t2=0; for(j=0;j<t1;j++) if(b[t2]==pC[i].a[j] && t2<flag) { for(int n=j;n<t1;n++) pC[i].a[n]=pC[i].a[n+1]; pC[i].count--; t2++; if(pC[i].count==0) break; } printf("输出删除后的集合元素的个数:%d ",pC[i].count); printf("输出删除后的集合pC[%d]: ",i); for(j=0;j<pC[i].count;j++) printf(" %d ",pC[i].a[j]); printf("/n/n"); */ } for(i=0;i<SRMax;i++) { int t1=pC[i].count; int t2=0; for(int j=0;j<t1;j++) if(b[t2]==pC[i].a[j] && t2<flag) { if(t2==flag-1) { for(int n=j;n<t1;n++) { if(n+1==t1) break; // pC[i].a[n]=pC[i].a[n+1]; pC[i].a[n+1-flag]=pC[i].a[n+1]; } } pC[i].count--; t2++; if(pC[i].count==0) break; } printf("输出删除后的集合元素的个数:%d ",pC[i].count); printf("输出删除后的集合pC[%d]: ",i); for(j=0;j<pC[i].count;j++) printf(" %d ",pC[i].a[j]); printf("/n/n"); } } int ISM::JHQD(int a[],int b[],int count) //集合是否相等 { for(int i=0;i<count;i++) if(a[i]!=b[i]) { return 0; break; } return count; } //////////////////////////////////////////////关于错误////////////////////////////////////////////////////// /* int ISM::JHQD(int a[],int b[],int count) //集合是否相等 { if(count<=0) exit(0); //改正 // break; // error C2043: illegal break for(int i=0;i<count;i++) if(a[i]!=b[i]) { return 0; break; } return count; } */
main.cpp
#include "ISM.H" void main() { ISM ism; ism.CreateAvailableArray(); ism.CJGraplic(); }
程序结果: (一)第一组测试数据,按程序步骤截图如下
(1)按图输入得邻接矩阵
(2)求可达矩阵
(3)求可达矩阵和先行矩阵
(4)求可达矩阵和先行矩阵的交集;并且求该交集与可达矩阵是否相等
(5)输出最后的层数
(二)第二组测试数据结果如下图:按程序步骤截图如下:
(1)按图输入得邻接矩阵
(2)求可达矩阵
(3)求可达矩阵和先行矩阵
(4)求可达矩阵和先行矩阵的交集;并且求该交集与可达矩阵是否相等
(5)输出最后的层数