稀疏矩阵的运算(完美版)

合集下载

稀疏矩阵求逆

稀疏矩阵求逆

稀疏矩阵求逆一、稀疏矩阵的定义和特点稀疏矩阵是指其中绝大部分元素都为0的矩阵。

与之相对的是密集矩阵,即绝大部分元素都不为0的矩阵。

稀疏矩阵在实际应用中非常常见,例如在图像处理、网络分析等领域中,经常需要处理大规模的稀疏数据。

二、求逆的概念和方法求逆是指对于一个n×n的方阵A,找到一个n×n的方阵B,使得AB=BA=In(其中In表示n×n的单位矩阵)。

如果A可逆,则B称为A的逆。

求逆是线性代数中非常重要的一个概念,在实际应用中也有广泛的应用。

求解一个密集矩阵的逆可以使用高斯-约旦消元法或LU分解等方法,但是这些方法在处理稀疏矩阵时效率较低。

因此,针对稀疏矩阵求逆问题需要采用特殊的算法。

三、基于LU分解的稀疏矩阵求逆算法1. LU分解首先介绍一下LU分解算法。

对于一个非奇异的n×n矩阵A,可以将其分解为一个下三角矩阵L和一个上三角矩阵U的乘积,即A=LU。

其中L和U都是非奇异的矩阵,且L的对角线元素为1。

LU分解算法可以使用高斯消元法来实现。

具体步骤如下:(1)对于A中的第i行,进行行变换,使得第i个元素成为主元(即绝对值最大的元素)。

(2)将第i+1到n行中第i个元素除以主元,得到一个系数ki。

(3)将第i+1到n行中第i列的所有元素减去ki倍的第i行中相应位置的元素。

重复以上步骤直到完成LU分解。

2. 稀疏矩阵求逆算法基于LU分解的稀疏矩阵求逆算法可以分为以下几个步骤:(1)对于稀疏矩阵A,使用稀疏存储方式将其存储在计算机内存中。

(2)使用LU分解算法求出L和U两个稀疏矩阵。

由于L和U都是三角形矩阵,因此它们也是稀疏的。

(3)根据AB=In,可以得到B=U^-1L^-1。

因此,我们需要分别求出U和L的逆矩阵。

(4)对于U^-1和L^-1,可以使用前/后代法(forward/backward substitution)求解。

具体来说,对于一个下三角矩阵L和一个向量b,可以使用前代法求解方程Ly=b;对于一个上三角矩阵U和一个向量y,可以使用后代法求解方程Ux=y。

稀疏矩阵的计算

稀疏矩阵的计算

#include <stdio.h>#include <malloc.h>#include<stdlib.h>typedef int ElemType;// 稀疏矩阵的十字链表存储表示typedef struct OLNode{int i,j; // 该非零元的行和列下标ElemType e; // 非零元素值struct OLNode *right,*down; // 该非零元所在行表和列表的后继链域}OLNode, *OLink;typedef struct// 行和列链表头指针向量基址,由CreatSMatrix_OL()分配{OLink *rhead, *chead;int mu, nu, tu; // 稀疏矩阵的行数、列数和非零元个数}CrossList;// 初始化M(CrossList类型的变量必须初始化,否则创建、复制矩阵将出错) int InitSMatrix(CrossList *M){(*M).rhead=(*M).chead=NULL;(*M).mu=(*M).nu=(*M).tu=0;return 1;}// 销毁稀疏矩阵Mint DestroySMatrix(CrossList *M){int i;OLNode *p,*q;for(i=1;i<=(*M).mu;i++) // 按行释放结点{p=*((*M).rhead+i);while(p){q=p;p=p->right;free(q);}}free((*M).rhead);free((*M).chead);(*M).rhead=(*M).chead=NULL;(*M).mu=(*M).nu=(*M).tu=0;return 1;}// 创建稀疏矩阵M,采用十字链表存储表示。

int CreateSMatrix(CrossList *M){int i,j,k,m,n,t;ElemType e;OLNode *p,*q;if((*M).rhead)DestroySMatrix(M);printf("请输入稀疏矩阵的行数列数非零元个数:(space) ");scanf("%d%d%d",&m,&n,&t);(*M).mu=m;(*M).nu=n;(*M).tu=t;//初始化行链表头(*M).rhead=(OLink*)malloc((m+1)*sizeof(OLink));if(!(*M).rhead)exit(0);//初始化列链表头(*M).chead=(OLink*)malloc((n+1)*sizeof(OLink));if(!(*M).chead)exit(0);for(k=1;k<=m;k++) // 初始化行头指针向量;各行链表为空链表(*M).rhead[k]=NULL;for(k=1;k<=n;k++) // 初始化列头指针向量;各列链表为空链表(*M).chead[k]=NULL;printf("请按任意次序输入%d个非零元的行列元素值:(空格)\n",(*M).tu);for(k=0;k<t;k++){scanf("%d%d%d",&i,&j,&e);p=(OLNode*)malloc(sizeof(OLNode));if(!p)exit(0);p->i=i; // 生成结点p->j=j;p->e=e;if((*M).rhead[i]==NULL||(*M).rhead[i]->j>j){// p插在该行的第一个结点处p->right=(*M).rhead[i];(*M).rhead[i]=p;}else // 寻查在行表中的插入位置{//从该行的行链表头开始,直到找到for(q=(*M).rhead[i]; q->right && q->right->j < j;q = q->right);p->right=q->right; // 完成行插入q->right=p;}if((*M).chead[j] == NULL || (*M).chead[j]->i > i){// p插在该列的第一个结点处p->down = (*M).chead[j];(*M).chead[j] = p;}else // 寻查在列表中的插入位置{for(q = (*M).chead[j];q->down && q->down->i < i;q = q->down);p->down=q->down; // 完成列插入q->down=p;}}return 1;}// 按行或按列输出稀疏矩阵Mint PrintSMatrix(CrossList M){int i,j;OLink p;printf("%d行%d列%d个非零元素\n",M.mu,M.nu,M.tu);printf("请输入选择(1.按行输出2.按列输出): ");scanf("%d",&i);switch(i){case 1:for(j=1;j<=M.mu;j++){p=M.rhead[j];while(p){printf("%d行%d列值为%d\n",p->i,p->j,p->e);p=p->right;}}break;case 2:for(j=1;j<=M.nu;j++){p=M.chead[j];while(p){printf("%d行%d列值为%d\n",p->i,p->j,p->e);p=p->down;}}}return 1;}// 由稀疏矩阵M复制得到Tint CopySMatrix(CrossList M,CrossList *T){int i;OLink p,q,q1,q2;if((*T).rhead)DestroySMatrix(T);(*T).mu=M.mu;(*T).nu=M.nu;(*T).tu=M.tu;(*T).rhead=(OLink*)malloc((M.mu+1)*sizeof(OLink));if(!(*T).rhead)exit(0);(*T).chead=(OLink*)malloc((M.nu+1)*sizeof(OLink));if(!(*T).chead)exit(0);for(i=1;i<=M.mu;i++) // 初始化矩阵T的行头指针向量;各行链表为空链表(*T).rhead[i]=NULL;for(i=1;i<=M.nu;i++) // 初始化矩阵T的列头指针向量;各列链表为空链表(*T).chead[i]=NULL;for(i=1;i<=M.mu;i++) // 按行复制{p=M.rhead[i];while(p) // 没到行尾{q=(OLNode*)malloc(sizeof(OLNode)); // 生成结点if(!q)exit(0);q->i=p->i; // 给结点赋值q->j=p->j;q->e=p->e;if(!(*T).rhead[i]) // 插在行表头(*T).rhead[i]=q1=q;else // 插在行表尾q1=q1->right=q;if(!(*T).chead[q->j]) // 插在列表头{(*T).chead[q->j]=q;q->down=NULL;}else // 插在列表尾{q2=(*T).chead[q->j];while(q2->down)q2=q2->down;q2->down=q;q->down=NULL;}p=p->right;}q->right=NULL;}return 1;}// 求稀疏矩阵的和Q=M+Nint AddSMatrix(CrossList M,CrossList N,CrossList *Q){int i,k;OLink p,pq,pm,pn;OLink *col;if(M.mu!=N.mu||M.nu!=N.nu){printf("两个矩阵不是同类型的,不能相加\n");exit(0);}(*Q).mu=M.mu; // 初始化Q矩阵(*Q).nu=M.nu;(*Q).tu=0; // 元素个数的初值(*Q).rhead=(OLink*)malloc(((*Q).mu+1)*sizeof(OLink));if(!(*Q).rhead)exit(0);(*Q).chead=(OLink*)malloc(((*Q).nu+1)*sizeof(OLink));if(!(*Q).chead)exit(0);for(k=1;k<=(*Q).mu;k++) // 初始化Q的行头指针向量;各行链表为空链表(*Q).rhead[k]=NULL;for(k=1;k<=(*Q).nu;k++) // 初始化Q的列头指针向量;各列链表为空链表(*Q).chead[k]=NULL;// 生成指向列的最后结点的数组col=(OLink*)malloc(((*Q).nu+1)*sizeof(OLink));if(!col)exit(0);for(k=1;k<=(*Q).nu;k++) // 赋初值col[k]=NULL;for(i=1;i<=M.mu;i++) // 按行的顺序相加{pm=M.rhead[i]; // pm指向矩阵M的第i行的第1个结点pn=N.rhead[i]; // pn指向矩阵N的第i行的第1个结点while(pm&&pn) // pm和pn均不空{if(pm->j<pn->j) // 矩阵M当前结点的列小于矩阵N当前结点的列{p=(OLink)malloc(sizeof(OLNode)); // 生成矩阵Q的结点if(!p)exit(0);(*Q).tu++; // 非零元素数加1p->i=i; // 给结点赋值p->j=pm->j;p->e=pm->e;p->right=NULL;pm=pm->right; // pm指针向右移}else if(pm->j>pn->j)// 矩阵M当前结点的列大于矩阵N当前结点的列{p=(OLink)malloc(sizeof(OLNode)); // 生成矩阵Q的结点if(!p)exit(0);(*Q).tu++; // 非零元素数加1p->i=i; // 给结点赋值p->j=pn->j;p->e=pn->e;p->right=NULL;pn=pn->right; // pn指针向右移}// 矩阵M、N当前结点的列相等且两元素之和不为0else if(pm->e+pn->e){p=(OLink)malloc(sizeof(OLNode)); // 生成矩阵Q的结点if(!p)exit(0);(*Q).tu++; // 非零元素数加1p->i=i; // 给结点赋值p->j=pn->j;p->e=pm->e+pn->e;p->right=NULL;pm=pm->right; // pm指针向右移pn=pn->right; // pn指针向右移}else // 矩阵M、N当前结点的列相等且两元素之和为0{pm=pm->right; // pm指针向右移pn=pn->right; // pn指针向右移continue;}if((*Q).rhead[i]==NULL) // p为该行的第1个结点// p插在该行的表头且pq指向p(该行的最后一个结点)(*Q).rhead[i]=pq=p;else // 插在pq所指结点之后{pq->right=p; // 完成行插入pq=pq->right; // pq指向该行的最后一个结点}if((*Q).chead[p->j]==NULL) // p为该列的第1个结点// p插在该列的表头且col[p->j]指向p(*Q).chead[p->j]=col[p->j]=p;else // 插在col[p->]所指结点之后{col[p->j]->down=p; // 完成列插入// col[p->j]指向该列的最后一个结点col[p->j]=col[p->j]->down;}}while(pm) // 将矩阵M该行的剩余元素插入矩阵Q{p=(OLink)malloc(sizeof(OLNode)); // 生成矩阵Q的结点if(!p)exit(0);(*Q).tu++; // 非零元素数加1p->i=i; // 给结点赋值p->j=pm->j;p->e=pm->e;p->right=NULL;pm=pm->right; // pm指针向右移if((*Q).rhead[i] == NULL) // p为该行的第1个结点// p插在该行的表头且pq指向p(该行的最后一个结点)(*Q).rhead[i] = pq = p;else // 插在pq所指结点之后{pq->right=p; // 完成行插入pq=pq->right; // pq指向该行的最后一个结点}if((*Q).chead[p->j] == NULL) // p为该列的第1个结点// p插在该列的表头且col[p->j]指向p(*Q).chead[p->j] = col[p->j] = p;else // 插在col[p->j]所指结点之后{col[p->j]->down=p; // 完成列插入// col[p->j]指向该列的最后一个结点col[p->j]=col[p->j]->down;}}while(pn) // 将矩阵N该行的剩余元素插入矩阵Q{p=(OLink)malloc(sizeof(OLNode)); // 生成矩阵Q的结点if(!p)exit(0);(*Q).tu++; // 非零元素数加1p->i=i; // 给结点赋值p->j=pn->j;p->e=pn->e;p->right=NULL;pn=pn->right; // pm指针向右移if((*Q).rhead[i]==NULL) // p为该行的第1个结点// p插在该行的表头且pq指向p(该行的最后一个结点)(*Q).rhead[i]=pq=p;else // 插在pq所指结点之后{pq->right=p; // 完成行插入pq=pq->right; // pq指向该行的最后一个结点}if((*Q).chead[p->j]==NULL) // p为该列的第1个结点// p插在该列的表头且col[p->j]指向p(*Q).chead[p->j]=col[p->j]=p;else // 插在col[p->j]所指结点之后{col[p->j]->down=p; // 完成列插入// col[p->j]指向该列的最后一个结点col[p->j]=col[p->j]->down;}}}for(k=1;k<=(*Q).nu;k++)if(col[k]) // k列有结点col[k]->down=NULL; // 令该列最后一个结点的down指针为空free(col);return 1;}// 求稀疏矩阵的差Q=M-Nint SubtSMatrix(CrossList M,CrossList N,CrossList *Q){int i,k;OLink p,pq,pm,pn;OLink *col;if(M.mu!=N.mu||M.nu!=N.nu){printf("两个矩阵不是同类型的,不能相加\n");exit(0);}(*Q).mu=M.mu; // 初始化Q矩阵(*Q).nu=M.nu;(*Q).tu=0; // 元素个数的初值(*Q).rhead=(OLink*)malloc(((*Q).mu+1)*sizeof(OLink));if(!(*Q).rhead)exit(0);(*Q).chead=(OLink*)malloc(((*Q).nu+1)*sizeof(OLink));if(!(*Q).chead)exit(0);for(k=1;k<=(*Q).mu;k++) // 初始化Q的行头指针向量;各行链表为空链表(*Q).rhead[k]=NULL;for(k=1;k<=(*Q).nu;k++) // 初始化Q的列头指针向量;各列链表为空链表(*Q).chead[k]=NULL;// 生成指向列的最后结点的数组col=(OLink*)malloc(((*Q).nu+1)*sizeof(OLink));if(!col)exit(0);for(k=1;k<=(*Q).nu;k++) // 赋初值col[k]=NULL;for(i=1;i<=M.mu;i++) // 按行的顺序相加{pm=M.rhead[i]; // pm指向矩阵M的第i行的第1个结点pn=N.rhead[i]; // pn指向矩阵N的第i行的第1个结点while(pm&&pn) // pm和pn均不空{if(pm->j<pn->j) // 矩阵M当前结点的列小于矩阵N当前结点的列{p=(OLink)malloc(sizeof(OLNode)); // 生成矩阵Q的结点if(!p)exit(0);(*Q).tu++; // 非零元素数加1p->i=i; // 给结点赋值p->j=pm->j;p->e=pm->e;p->right=NULL;pm=pm->right; // pm指针向右移}// 矩阵M当前结点的列大于矩阵N当前结点的列else if(pm->j>pn->j){p=(OLink)malloc(sizeof(OLNode)); // 生成矩阵Q的结点if(!p)exit(0);(*Q).tu++; // 非零元素数加1p->i=i; // 给结点赋值p->j=pn->j;p->e=-pn->e;p->right=NULL;pn=pn->right; // pn指针向右移}else if(pm->e-pn->e){// 矩阵M、N当前结点的列相等且两元素之差不为0p=(OLink)malloc(sizeof(OLNode)); // 生成矩阵Q的结点if(!p)exit(0);(*Q).tu++; // 非零元素数加1p->i=i; // 给结点赋值p->j=pn->j;p->e=pm->e-pn->e;p->right=NULL;pm=pm->right; // pm指针向右移pn=pn->right; // pn指针向右移}else // 矩阵M、N当前结点的列相等且两元素之差为0{pm=pm->right; // pm指针向右移pn=pn->right; // pn指针向右移continue;}if((*Q).rhead[i]==NULL) // p为该行的第1个结点// p插在该行的表头且pq指向p(该行的最后一个结点)(*Q).rhead[i]=pq=p;else // 插在pq所指结点之后{pq->right=p; // 完成行插入pq=pq->right; // pq指向该行的最后一个结点}if((*Q).chead[p->j]==NULL) // p为该列的第1个结点// p插在该列的表头且col[p->j]指向p(*Q).chead[p->j]=col[p->j]=p;else // 插在col[p->]所指结点之后{col[p->j]->down=p; // 完成列插入// col[p->j]指向该列的最后一个结点col[p->j]=col[p->j]->down;}}while(pm) // 将矩阵M该行的剩余元素插入矩阵Q{p=(OLink)malloc(sizeof(OLNode)); // 生成矩阵Q的结点if(!p)exit(0);(*Q).tu++; // 非零元素数加1p->i=i; // 给结点赋值p->j=pm->j;p->e=pm->e;p->right=NULL;pm=pm->right; // pm指针向右移if((*Q).rhead[i]==NULL) // p为该行的第1个结点// p插在该行的表头且pq指向p(该行的最后一个结点)(*Q).rhead[i]=pq=p;else // 插在pq所指结点之后{pq->right=p; // 完成行插入pq=pq->right; // pq指向该行的最后一个结点}if((*Q).chead[p->j]==NULL) // p为该列的第1个结点// p插在该列的表头且col[p->j]指向p(*Q).chead[p->j]=col[p->j]=p;else // 插在col[p->j]所指结点之后{col[p->j]->down=p; // 完成列插入// col[p->j]指向该列的最后一个结点col[p->j]=col[p->j]->down;}}while(pn) // 将矩阵N该行的剩余元素插入矩阵Q{p=(OLink)malloc(sizeof(OLNode)); // 生成矩阵Q的结点if(!p)exit(0);(*Q).tu++; // 非零元素数加1p->i=i; // 给结点赋值p->j=pn->j;p->e=-pn->e;p->right=NULL;pn=pn->right; // pm指针向右移if((*Q).rhead[i]==NULL) // p为该行的第1个结点// p插在该行的表头且pq指向p(该行的最后一个结点)(*Q).rhead[i]=pq=p;else // 插在pq所指结点之后{pq->right=p; // 完成行插入pq=pq->right; // pq指向该行的最后一个结点}if((*Q).chead[p->j]==NULL) // p为该列的第1个结点// p插在该列的表头且col[p->j]指向p(*Q).chead[p->j]=col[p->j]=p;else // 插在col[p->j]所指结点之后{col[p->j]->down=p; // 完成列插入// col[p->j]指向该列的最后一个结点col[p->j]=col[p->j]->down;}}}for(k=1;k<=(*Q).nu;k++)if(col[k]) // k列有结点col[k]->down=NULL; // 令该列最后一个结点的down指针为空free(col);return 1;}// 求稀疏矩阵乘积Q=M*Nint MultSMatrix(CrossList M,CrossList N,CrossList *Q){int i,j,e;OLink q,p0,q0,q1,q2;InitSMatrix(Q);(*Q).mu=M.mu;(*Q).nu=N.nu;(*Q).tu=0;(*Q).rhead=(OLink*)malloc(((*Q).mu+1)*sizeof(OLink));if(!(*Q).rhead)exit(0);(*Q).chead=(OLink*)malloc(((*Q).nu+1)*sizeof(OLink));if(!(*Q).chead)exit(0);for(i=1;i<=(*Q).mu;i++) // 初始化矩阵Q的行头指针向量;各行链表为空链表(*Q).rhead[i]=NULL;for(i=1;i<=(*Q).nu;i++) // 初始化矩阵Q的列头指针向量;各列链表为空链表(*Q).chead[i]=NULL;for(i=1;i<=(*Q).mu;i++)for(j=1;j<=(*Q).nu;j++){p0=M.rhead[i];q0=N.chead[j];e=0;while(p0&&q0){if(q0->i<p0->j)q0=q0->down; // 列指针后移else if(q0->i>p0->j)p0=p0->right; // 行指针后移else // q0->i==p0->j{e+=p0->e*q0->e; // 乘积累加q0=q0->down; // 行列指针均后移p0=p0->right;}}if(e) // 值不为0{(*Q).tu++; // 非零元素数加1q=(OLink)malloc(sizeof(OLNode)); // 生成结点if(!q) // 生成结点失败exit(0);q->i=i; // 给结点赋值q->j=j;q->e=e;q->right=NULL;q->down=NULL;if(!(*Q).rhead[i]) // 行表空时插在行表头(*Q).rhead[i]=q1=q;else // 否则插在行表尾q1=q1->right=q;if(!(*Q).chead[j]) // 列表空时插在列表头(*Q).chead[j]=q;else // 否则插在列表尾{q2=(*Q).chead[j]; // q2指向j行第1个结点while(q2->down)q2=q2->down; // q2指向j行最后1个结点q2->down=q;}}}return 1;}// 求稀疏矩阵M的转置矩阵Tint TransposeSMatrix(CrossList M,CrossList *T){int u,i;OLink *head,p,q,r;if((*T).rhead)DestroySMatrix(T);CopySMatrix(M,T); // T=Mu=(*T).mu; // 交换(*T).mu和(*T).nu(*T).mu=(*T).nu;(*T).nu=u;head=(*T).rhead; // 交换(*T).rhead和(*T).chead(*T).rhead=(*T).chead;(*T).chead=head;for(u=1;u<=(*T).mu;u++) // 对T的每一行{p=(*T).rhead[u]; // p为行表头while(p) // 没到表尾,对T的每一结点{q=p->down; // q指向下一个结点i=p->i; // 交换.i和.jp->i=p->j;p->j=i;r=p->down; // 交换.down.和rightp->down=p->right;p->right=r;p=q; // p指向下一个结点}}return 1;}int main(){CrossList A,B,C;InitSMatrix(&A); // CrossList类型的变量在初次使用之前必须初始化InitSMatrix(&B);printf("创建矩阵A: ");CreateSMatrix(&A);PrintSMatrix(A);printf("由矩阵A复制矩阵B: ");CopySMatrix(A,&B);PrintSMatrix(B);DestroySMatrix(&B); // CrossList类型的变量在再次使用之前必须先销毁printf("销毁矩阵B后:\n");PrintSMatrix(B);printf("创建矩阵B2:(与矩阵A的行、列数相同,行、列分别为%d,%d)\n",A.mu,A.nu);CreateSMatrix(&B);PrintSMatrix(B);printf("矩阵C1(A+B): ");AddSMatrix(A,B,&C);PrintSMatrix(C);DestroySMatrix(&C);printf("矩阵C2(A-B): ");SubtSMatrix(A,B,&C);PrintSMatrix(C);DestroySMatrix(&C);printf("矩阵C3(A的转置): ");TransposeSMatrix(A,&C);PrintSMatrix(C);DestroySMatrix(&A);DestroySMatrix(&B);DestroySMatrix(&C);printf("创建矩阵A2: ");CreateSMatrix(&A);PrintSMatrix(A);printf("创建矩阵B3:(行数应与矩阵A2的列数相同=%d)\n",A.nu);CreateSMatrix(&B);PrintSMatrix(B);printf("矩阵C5(A*B): ");MultSMatrix(A,B,&C);PrintSMatrix(C);DestroySMatrix(&A);DestroySMatrix(&B);DestroySMatrix(&C);system("pause");return 0;}。

数据结构实验报告稀疏矩阵运算

数据结构实验报告稀疏矩阵运算

数据结构实验报告稀疏矩阵运算实验目的:1.学习并理解稀疏矩阵的概念、特点以及存储方式。

2.掌握稀疏矩阵加法、乘法运算的基本思想和算法。

3.实现稀疏矩阵加法、乘法的算法,并进行性能测试和分析。

实验原理:稀疏矩阵是指矩阵中绝大多数元素为0的矩阵。

在实际问题中,有许多矩阵具有稀疏性,例如文本矩阵、图像矩阵等。

由于存储稀疏矩阵时,对于大量的零元素进行存储是一种浪费空间的行为,因此需要采用一种特殊的存储方式。

常见的稀疏矩阵的存储方式有三元组顺序表、十字链表、行逻辑链接表等。

其中,三元组顺序表是最简单直观的一种方式,它是将非零元素按行优先的顺序存储起来,每个元素由三个参数组成:行号、列号和元素值。

此外,还需要记录稀疏矩阵的行数、列数和非零元素个数。

稀疏矩阵加法的原理是将两个稀疏矩阵按照相同的行、列顺序进行遍历,对于相同位置的元素进行相加,得到结果矩阵。

稀疏矩阵乘法的原理是将两个稀疏矩阵按照乘法的定义进行计算,即行乘以列的和。

实验步骤:1.实现稀疏矩阵的三元组顺序表存储方式,并完成稀疏矩阵的初始化、转置、打印等基本操作。

2.实现稀疏矩阵的加法运算,并进行性能测试和分析。

3.实现稀疏矩阵的乘法运算,并进行性能测试和分析。

4.编写实验报告。

实验结果:经过实验测试,稀疏矩阵的加法和乘法算法都能正确运行,并且在处理稀疏矩阵时能够有效节省存储空间。

性能测试结果表明,稀疏矩阵加法、乘法的运行时间与非零元素个数有关,当非零元素个数较少时,运算速度较快;当非零元素个数较多时,运算速度较慢。

实验分析:稀疏矩阵的运算相对于普通矩阵的运算有明显的优势,可以节省存储空间和运算时间。

在实际应用中,稀疏矩阵的存储方式和运算算法都可以进行优化。

例如,可以采用行逻辑链接表的方式存储稀疏矩阵,进一步减少存储空间的占用;可以采用并行计算的策略加快稀疏矩阵的运算速度。

总结:通过本次实验,我深入学习了稀疏矩阵的概念、特点和存储方式,掌握了稀疏矩阵加法、乘法的基本思想和算法,并通过实验实现了稀疏矩阵的加法、乘法运算。

稀疏矩阵加法乘法

稀疏矩阵加法乘法

稀疏矩阵加法乘法稀疏矩阵是指其中大部分元素都是0的矩阵,而只有极小部分元素为非0值。

与密集矩阵相比,稀疏矩阵具有更高的压缩率以及更快的计算速度,因此在大型数据处理和机器学习等领域中得到了广泛应用。

稀疏矩阵加法和乘法是稀疏矩阵计算中最基本的两个操作。

一、稀疏矩阵的表示方法基于稀疏矩阵的特殊性质,我们通常使用三元组(TUPLES)实现稀疏矩阵的存储。

三元组存储方式将一个i * j的稀疏矩阵表示为三个一维数组,分别存储非零元素的值,行坐标和列坐标。

例如,一个矩阵:1 0 00 2 00 0 3通过三元组存储方式可以表示为:value = [1, 2, 3]row = [0, 1, 2]col = [0, 1, 2]值为1的元素位于第0行第0列,值为2的元素位于第1行第1列,值为3的元素位于第2行第2列。

二、稀疏矩阵的加法两个稀疏矩阵相加的操作可以通过对两个矩阵的三元组进行合并,对于重复的元素,则将它们的值相加。

例如,对于两个矩阵A和B:A:1 0 00 2 00 0 3B:1 0 00 2 00 0 3则可以通过以下方式对A和B进行加法操作:value = [1+1, 2+2, 3+3]row = [0, 1, 2]col = [0, 1, 2]即结果矩阵为:2 0 00 4 00 0 6三、稀疏矩阵的乘法稀疏矩阵乘法的实现比较复杂,首先需要明确一点,即两个矩阵相乘的结果不一定是稀疏矩阵。

我们可以使用两种常见的算法实现稀疏矩阵的乘法:COO算法和CSR算法。

1. COO算法COO算法也称坐标格式算法,其基本思路是将两个矩阵的三元组转换成一个三元组,然后依次进行乘法运算,最后将结果累加得到最终结果的三元组。

例如,对于两个矩阵A和B:A:1 23 4B:5 67 8则可以按照以下步骤进行乘法操作:①将矩阵A表示为三元组形式:value_A = [1,2,3,4]row_A = [0,0,1,1]col_A = [0,1,0,1]②将矩阵B表示为三元组形式:value_B = [5,6,7,8]row_B = [0,0,1,1]col_B = [0,1,0,1]③对A和B的三元组进行合并得到三元组C:value_C = [1,2,3,4,5,6,7,8]row_C = [0,0,1,1,0,0,1,1]col_C = [0,1,0,1,1,0,1,0]其中row_C和col_C表示的是C中每个元素对应的行数和列数。

稀疏矩阵的运算

稀疏矩阵的运算

稀疏矩阵的运算稀疏矩阵的运算稀疏矩阵,顾名思义,就是矩阵中空值(0)的比例很大,而实际值(非0)的比例很小的矩阵。

它最大的特点就是,当矩阵的规模增大时,仍然可以保持较低的计算量。

在运算时,因为稀疏矩阵中的0值没有意义,所以对其做运算也没有意义。

所以,在运算中需要把稀疏矩阵转换成一维数组,即只保留其有意义的值。

下面介绍几种常用的稀疏矩阵运算技术。

1.索引表(Indextable)这是一种最简单的稀疏矩阵运算技术,在使用索引表时,需要用一个额外的一维数组来保存有意义的值的位置,而把矩阵本身变成一维数组,进行运算。

例如矩阵A:1 0 0 0 00 0 0 4 00 0 0 0 00 3 0 0 00 0 7 0 0这样的矩阵,可以使用一个一维数组来保存其有意义的值及其位置,例如:[1,(0,0); 4,(1,3); 3,(3,1); 7,(2,2)]这样,我们就可以用简单的一维数组代替复杂的二维矩阵,从而加快稀疏矩阵的运算。

2.矩阵向量乘法(Matrix-Vector Multiplication)这是一种最常用的稀疏矩阵运算技术,把一个大的稀疏矩阵A和一个向量(一维数组)V作乘法,得到一个新的向量C,即:C = A * V对于上面的实例,可以用以下方式求出C:C[0] = 1 * V[0] + 0 * V[1] + 0 * V[2] + 0 * V[3] + 0 * V[4] C[1] = 0 * V[0] + 0 * V[1] + 0 * V[2] + 4 * V[3] + 0 * V[4] C[2] = 0 * V[0] + 0 * V[1] + 0 * V[2] + 0 * V[3] + 7 * V[4] C[3] = 0 * V[0] + 3 * V[1] + 0 * V[2] + 0 * V[3] + 0 * V[4] 3.矩阵乘法(Matrix Multiplication)矩阵乘法也是一种常用的稀疏矩阵运算技术,把两个大的稀疏矩阵A和B相乘,得到一个新的稀疏矩阵C,即:C = A * B以上就是稀疏矩阵运算的一些常用技术,稀疏矩阵也可以用于解决很多复杂的运算问题,例如机器学习和深度学习等。

稀疏矩阵乘法

稀疏矩阵乘法

稀疏矩阵乘法给定两个 A 和 B,返回AB的结果。

您可以假设A的列数等于B的⾏数。

本参考程序来⾃九章算法,由 @Roger 提供。

题⽬解法:时间复杂度分析:假设矩阵A,B均为 n x n 的矩阵,矩阵A的稀疏系数为a,矩阵B的稀疏系数为b,a,b∈[0, 1],矩阵越稀疏,系数越⼩。

⽅法⼀:暴⼒,不考虑稀疏性Time (n^2 * (1 + n)) = O(n^2 + n^3)Space O(1)⽅法⼆:改进,仅考虑A的稀疏性Time O(n^2 * (1 + a * n) = O(n^2 + a * n^3)Space O(1)⽅法三(最优):进⼀步改进,考虑A与B的稀疏性Time O(n^2 * (1 + a * b * n)) = O(n^2 + a * b * n^3)Space O(b * n^2)⽅法四:另外⼀种思路,将矩阵A, B⾮0元素的坐标抽出,对⾮0元素进⾏运算和结果累加Time O(2 * n^2 + a * b * n^4) = O(n^2 + a * b * n^4)Space O(a * n^2 + b * n^2)解读:矩阵乘法的两种形式,假设 A(n, t) * B(t, m) = C(n, m)// 形式⼀:外层两个循环遍历C (常规解法)for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {for (int k = 0; k < t; k++) {C[i][j] += A[i][k] * B[k][j];}}}// 或者写成下⾯这样⼦for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {int sum = 0;for (int k = 0; k < t; k++) {sum += A[i][k] * B[k][j];}C[i][j] = sum;}}// 形式⼆:外层两个循环遍历Afor (int i = 0; i < n; i++) {for (int k = 0; k < t; k++) {for (int j = 0; j < m; j++) {C[i][j] += A[i][k] * B[k][j];}}}两种⽅法的区别代码上的区别(表象):调换了第⼆三层循环的顺序核⼼区别(内在):形式⼀以C为核⼼进⾏遍历,每个C[i][j]只会被计算⼀次,就是最终答案。

稀疏矩阵算法

稀疏矩阵算法

稀疏矩阵算法
稀疏矩阵算法是一种有效处理大规模矩阵数据的方法。

相比于普通矩阵,稀疏矩阵中绝大部分元素都是0,只有极少数非零元素。

因此,传统矩阵计算方法不仅浪费时间和空间,而且在处理稀疏矩阵时效率低下。

稀疏矩阵算法可以更加高效地处理稀疏矩阵,包括稀疏矩阵压缩、稀疏矩阵乘法、稀疏矩阵求逆等等。

其中,稀疏矩阵压缩主要有COO、CSR、CSC等三种压缩方式,可以将稀疏矩阵存储空间缩小至原来的几十倍,大大提高了矩阵数据的处理效率。

稀疏矩阵乘法则是通过优化矩阵乘法的算法,避免了对所有元素进行计算的浪费,从而实现了更加高效的计算。

稀疏矩阵求逆则是在矩阵求逆过程中,结合稀疏矩阵的特性,采用一些特殊的算法,从而有效地减少了计算时间和空间消耗。

稀疏矩阵算法不仅可以应用于数学、物理等领域的科学计算,还广泛应用于机器学习、计算机视觉、自然语言处理等人工智能领域,成为了处理大规模矩阵数据的必备技术之一。

- 1 -。

稀疏矩阵的MapReduce计算方法

稀疏矩阵的MapReduce计算方法

1
Ubuntu介绍:
以桌面应用为主题的Linux操作系统。 支持x86、x64和ppc架构。 为什么我们使用Ubuntu? →界面非常友好 →对硬件的支持非常全面 →最适合做桌面系统的Linux发行版本 →容易上手,适合初学者
1
在Ubuntu下安装JDK:
通过U盘,把JDK压缩文件放入Linux系统中。(直接拖拽无效) 打开终端:鼠标右击屏幕可以找到。 在终端下输入:sudo tar zxvf ./jdk-7u9-linux-i586.tar.gz//解压命令 。 ④sudo mkdir /usr/lib/jvm 创建文件夹:在usr文件夹下的lib中。 ⑤sudo cp -r ~/jdk1.7.0_09/ /usr/lib/jvm/ 用最高权限将jdk1.7.0_09 文件夹复制到第四步创建的jvm文件夹下. ⑥profile使用文本编辑器打开,添加三行代码: export JAVA_HOME=/usr/lib/jvm/jdk1.7.0_09 export CLASSPATH=.:$JAVA_HOME/lib:$JAVA_HOME/jre/lib export PATH="$JAVA_HOME/bin:$PATH" 保存后关闭
1
MapReduce思想:
在 MapReduce 模型下,完成单词统计的具体步骤为: (1) 用户编写Map 程序对出现的单词Hello 产生中间结果 key/value 偶对,如<Hello,1>。 (2)这些分布产生的中间结果将按key 值的不同进行汇总处理, 产生key(word)相同的value 列表,如<Hello,1,1,1,⋯>,并作为 Reduce 阶段的输入,这个阶段的工作将MapReduce策略,把对全 局(或阶段性)计算结果有影响且有关联的value采用相同key 标志。 由于这种策略的简单抽象,因此用户可以较容易地把握局部和全局 关系,从而确保问题求解并行实现的正确性,并进一步降低并行分 布式编程的难度。

稀疏矩阵的存储和乘法操作

稀疏矩阵的存储和乘法操作

稀疏矩阵的存储和乘法操作⼀稀疏矩阵的存储1.三元组顺序表三元组表⽰法就是在存储⾮零元的同时,存储该元素所对应的⾏下标和列下标。

稀疏矩阵中的每⼀个⾮零元素由⼀个三元组(i,j,a ij)唯⼀确定。

矩阵中所有⾮零元素存放在由三元组组成的顺序表中(通常⽤数组)。

所以三元组的逻辑结构如下://————稀疏矩阵的三元组表⽰法————//#define MAX_SIZE 1500 //表⽰稀疏矩阵的⾮零元素的最⼤个数class Triple{int i,j;//表⽰⾮零元素的⾏下表和列下标int val;//⾮零元素的值,此处以int类型为例};class TSMatrix{Triple data[MAX_SIZE];int row_num,col_num,cnt;//稀疏矩阵的⾏数、列数以及⾮零元素的个数};注意,此处的⾮零元素的三元组是以⾏序为主序顺序排列的。

2.⾏逻辑链接顺序表⾏逻辑链接顺序表的实质就是在三元组顺序表的基础上加了⼀个数组,这个数组⽤于存储稀疏矩阵中每⾏的第⼀个⾮零元素的在三元组顺序表中的位置(此处⼀定要理解对,是在三元组顺序表中的位置)。

所以其逻辑结构如下://————稀疏矩阵的⾏逻辑链接表⽰法————//#define MAX_SIZE 1500 //表⽰稀疏矩阵的⾮零元素的最⼤个数#define MAX_ROW 1500 //表⽰稀疏矩阵的⾏数的最⼤个数class Triple{int i,j;//表⽰⾮零元素的⾏下表和列下标int val;//⾮零元素的值,此处以int类型为例};class RLSMatrix{Triple data[MAX_SIZE]; //⾮零元三元组表int rpos[MAX_ROW];//每⾏第⼀个⾮零元素的位置int row_num,col_num,cnt;//稀疏矩阵的⾏数、列数以及⾮零元素的个数};3.⼗字链表当稀疏矩阵的⾮零元个数和位置在操作过程中变化较⼤时,就不易采⽤顺序存储结构来表⽰三元组的线性表。

稀疏矩阵的求和运算

稀疏矩阵的求和运算

作业答案:针对稀疏矩阵的三种表示方法,写出两个矩阵的求和算法。

即若A, B, C为三个矩阵,求C = A + B.1.三元组顺序表三元组顺序表的C表示如下:#define MAXSIZE 12500typedef struct{int i, j; //非零元的行列下标ElemType e;}Triple;typedef union{Triple a_Data[MAXSIZE + 1]; //三元组表,a_Data[0]未用int mu, nu, tu;}TSMatrix;算法:注意:在稀疏矩阵的三元组顺序表表示中,a_Data域中的非零元排列是有序的,即以行序为主序排列,在一行中,数据元素按列序排列。

因此整个算法可以集中到如下问题:在已知A和B阵的某一行的起始位置的情况下,如何得到C的该行的内容。

如图示:C:A:B:kB kB’其中kA,kB,kC分别为矩阵A,B,C的a_Data域的当前位置。

kX到kX’的位置是矩阵X中第i行的非零元元素。

两个矩阵的加法运算转化为第i行元素的加法。

而第i行中第j元素的加法可以描述为:1.取A和B的当前元素,若列号相同,则相加,若和非零,把结果放在C中,kA,kB,kC分别移到下一个位置;若和为零,则kA,kB移到下一个位置;2.否则,若A的列号小于B,则C的元素等于A的元素,kA,kC分别移到下一个位置;3.否则,则C的元素等于B的元素,kB,kC分别移到下一个位置;程序:// 以知A和B,求矩阵C = A + B,其中矩阵采用三元组顺序表表示status MatrixAdd_TSMatrix( TSMatrix A, TSMatrix B, TSMatrix &C){// 若矩阵A和B的行列不同,返回错误!if( A.mu != B.mu || A.nu != B.nu ){return ERROR;}// 矩阵C的行列赋值C.mu = A.mu;C.nu = B.nu;kA = kB = kC = 1; // 初始化for ( i = 0; i < C.mu; i++) // 处理每一行{// 每列元素,从kA和kB开始,依次比较A和B中元素。

稀疏矩阵求和

稀疏矩阵求和

1、稀疏矩阵A和B用三元组表示,编写算法,计算C = A + B算法思想:依次扫描A和B的行号和列号如果A的当前项的行号等于B的当前项的行号,则比较其列号,将较小列的值存入C如果列号相等,则相应元素值相加存入C中如果A的当前项的行号小于B的当前项的行号,则将A的值存入C中如果A的当前项的行号大于B的当前项的行号,则将B的值存入C中void add( Matrix A, Matrix B, Matrix C){int i=1 ,j=1, k=1 ;while( i < A[0][2] && j <= B[0][2]){if( A[i][0] == B[j][0])// 如果A的当前项的行号等于B当前项的行号,则比较列号,将较小项存入C {if(A[i][1]< B[j][1]){C[k][0]= A[i][0];C[k][1]= A[i][1];C[k][2]= A[i][2];k++;i++;}else if(A[i][1]> B[j][1]){C[k][0]= B[j][0];C[k][1]= B[j][1];C[k][2]= B[j][2];k++;j++;}else // 如果行号和列号均相等,则将对应元素相加,求和结果存入C {C[k][0]= B[j][0];C[k][1]= B[j][1];C[k][2]= A[i][2]+B[j][2];If( C[k][2] !=0)k++;i++;j++;}}}else if (A[i][0] < B[j][0])// 如果A的当前项的行号小于B的当前项的行号,则将A项存入C{C[k][0]= A[i][0];C[k][1]= A[i][1];C[k][2]= A[i][2];k++;i++;}else// 如果A的当前项的行号大于B的当前项的行号,则将B项存入C {C[k][0]= B[j][0];C[k][1]= B[j][1];C[k][2]= B[j][2];k++;j++;}C[0][0]= A[0][0]; //产生第0行结果,行数,列数,非零元数个数C[0][1]= A[0][1];C[0][2]= k -1 ;}。

稀疏矩阵

稀疏矩阵

三 元 组 表 的 定 义
void Add() //向三元组添加元素 { } void Display() //显示三元组表中的元素 { } void MsTranspose(TsMatrix &T) //元素的转置 { }
};
1.三元组表的初始化
TsMatrix(int r,int c,int term) { rows=r; cols=c; maxterms=r*c; a=new Triple[maxterms]; terms=term; }
16
col 1
col
num[col] cpot[col]
1 2 1
2 2 3
3 2 5
4 1 7
5 1 8
6 0 8
M
规律: cpot[1]=1 cpot[col] = cpot[col-1] + num[col-1]
0 0 -3 0 0 15
12 0 0 0 18 0
2 3 4 5 6
9 0 0 24 0 0 0 0 0 0 0 -7 0 0 14 0 0 0
p 1 (1, 2, 12) 2 (1, 3, 9 ) 3 (3, 1, -3) 4 (3, 5, 14)
(4, 3, 24) (5, 2, 18) (6, 1, 15) (6, 4, -7)
q 1 2 3 5
三 元 组 表 M
(1, 3, -3) (1, 6, 15) (2 ,1, 12) (2, 5, 18) (3, 1, 9) (3, 4, 24) (4, 6, -7) (5, 3, 14)
14
24 18 15 -7
注意:为更可靠描述, 通常再加一行“总体” 信息:即总行数、总 列数、非零元素总个 数

三元组顺序表表示的稀疏矩阵加法

三元组顺序表表示的稀疏矩阵加法

三元组顺序表表示的稀疏矩阵加法三元组顺序表表示的稀疏矩阵加法引言:稀疏矩阵是指在矩阵中大部分元素为零的情况下,只有很少非零元素的矩阵。

由于矩阵运算的复杂性,对于大型稀疏矩阵,使用传统的矩阵加法算法会消耗大量的时间和内存资源。

因此,为了高效地进行稀疏矩阵的加法运算,可以使用三元组顺序表来表示稀疏矩阵,并通过特定的算法来实现加法操作。

本文将介绍三元组顺序表和稀疏矩阵加法,并逐步回答以下问题:1. 什么是三元组顺序表?2. 什么是稀疏矩阵加法?3. 如何使用三元组顺序表进行稀疏矩阵加法操作?一、什么是三元组顺序表?三元组顺序表是一种用来高效表示稀疏矩阵的数据结构。

在三元组顺序表中,每个非零元素用一个三元组表示,包括元素的行号、列号和值。

同时,三元组顺序表中还包含两个整数,分别表示矩阵的行数和列数。

例如,如果有一个3x3的稀疏矩阵如下:1 0 20 4 03 0 5使用三元组顺序表来表示这个矩阵,可以得到如下的三元组:(0, 0, 1), (0, 2, 2), (1, 1, 4), (2, 0, 3), (2, 2, 5)二、什么是稀疏矩阵加法?稀疏矩阵加法是指对两个稀疏矩阵进行加法运算的操作。

对于给定的两个稀疏矩阵A和B,稀疏矩阵加法的结果矩阵C的每个元素等于矩阵A和B中对应位置的元素之和。

三、使用三元组顺序表进行稀疏矩阵加法操作的步骤为了实现稀疏矩阵加法,可以按照以下步骤进行:1. 定义一个存储稀疏矩阵的三元组顺序表:使用一个结构体将矩阵的行、列和非零元素存储起来。

2. 输入矩阵A和B的维度:获取矩阵A和B的行数和列数,以及非零元素的个数。

3. 输入矩阵A和B的非零元素:获取矩阵A和B的非零元素的行号、列号和值,并将其存储到三元组顺序表中。

4. 对三元组顺序表进行排序:根据三元组的行号和列号进行排序,以便后续的加法运算。

5. 进行稀疏矩阵加法运算:从头开始遍历三元组顺序表,依次取出每个三元组,根据其行号和列号在结果矩阵C中进行加法运算。

稀疏矩阵的加、减、乘、求逆运算

稀疏矩阵的加、减、乘、求逆运算

稀疏矩阵的加、减、乘、求逆运算#include <iostream>#include <iomanip>using namespace std;const int MAXSIZE = 100; //定义非零元素的最多个数const int MAXROW = 10; //定义数组行数的最大值const int SIZENUM = 10;typedef struct //定义三元组元素{int r, c; //矩阵的行号和列号int v; //矩阵元素值}Triple;typedef struct //定义普通三元组对象{Triple data[MAXSIZE+1];int rows, cols, nzeroNums; //行数、列数、非零元素个数}TSMatrix;typedef struct //定义行逻辑链接的顺序表{Triple data[MAXSIZE+2]; //非0元三元组表int rpos[MAXROW+1]; //各行第一个非零元素的位置表int rows, cols, nzeroNums; //行数、列数、非零元素个数}RLSMatrix;//输入三元组矩阵template <class T>bool InputTSMatrix(T &M, int y){cout << "输入矩阵的行数、列数和非零元素个数: ";cin >> M.rows >> M.cols >> eroNums;cout << "请输入非零元素对应的行号、列号和相应的元素值: " << endl;for (int i = 1; i <= eroNums; i++){cin >> M.data[i].r >> M.data[i].c >> M.data[i].v;}return true;}//输出矩阵,按标准格式输出template <class T>bool OutputSMatrix(T M){int i, j, k = 1;for (i = 0; i < M.rows; i++){for (j = 0; j < M.cols; j++){if ((M.data[k].r-1) == i && (M.data[k].c-1) == j){cout << setw(4) << M.data[k].v;k++;}elsecout << setw(4) << "0";}//end_jcout << endl;}//end_ireturn true;}//求稀疏矩阵的转置int TranSMatrix(){TSMatrix M, T;InputTSMatrix(M, 0);int col, p, q = 1;T.rows = M.cols;T.cols = M.rows;eroNums = eroNums;if (eroNums){for (col = 1; col <= M.cols; col++){for (p = 1; p <= eroNums; p++){if (M.data[p].c == col){T.data[q].r = M.data[p].c;T.data[q].c = M.data[p].r;T.data[q].v = M.data[p].v;++q;}}//end_col}//end_ifcout << "运用普通转置算法, 输入矩阵的转置矩阵为: " << endl;OutputSMatrix(T);return 1;}//稀疏矩阵的快速转置int FastTranMat(){TSMatrix M, T;int num[MAXROW+1]; //表示矩阵M中第col列非零元素的个数int cpot[MAXROW+1]; //表示矩阵M中第col列第一个非0元素在b.data中的位置int p, q, col, t;InputTSMatrix(M, 0); //输入稀疏矩阵T.rows = M.cols;T.cols = M.rows;eroNums = eroNums;if (eroNums){for (col = 1; col <= M.cols; col++)//M中各列元素初始化{num[col] = 0;}for (t = 1; t <= eroNums; t++){++num[M.data[t].c]; //求M中每一列非零元个数}//求第col列第一个非零元在b.data中的序号cpot[1] = 1;for (col = 2; col <= M.cols; col++){cpot[col] = cpot[col-1] + num[col-1];}for (p = 1; p <= eroNums; p++){col = M.data[p].c; //稀疏矩阵M中每个元素对应的列号q = cpot[col]; //稀疏矩阵M中第一个非零元素位置T.data[q].r = M.data[p].c;T.data[q].c = M.data[p].r;T.data[q].v = M.data[p].v;++cpot[col];}//end_ifcout << "运用快速算法,输入矩阵的转置为: " << endl;OutputSMatrix(T);return 1;}//求取稀疏矩阵每一行非零元个数bool Count(RLSMatrix &M){int row, p;int num[MAXROW+1];for (row = 1; row <= M.rows; row++){num[row] = 0; //清零}for (p = 1; p <= eroNums; p++){++num[M.data[p].r]; //统计M每一行非零元个数}M.rpos[1] = 1;//M中每一行非零元的起始位置for (row = 2; row <= M.rows; row++){M.rpos[row] = M.rpos[row-1] + num[row-1];}return true;}//两个稀疏矩阵的乘法bool MultSMatrix(){RLSMatrix M, N, Q; //构建三个带链接信息的三元组表示的数组InputTSMatrix(M, 1); //用普通三元组形式输入数组InputTSMatrix(N, 1);Count(M);Count(N);if (M.cols != N.rows){cout << "Error!";return false;}//Q的初始化Q.rows = M.rows;Q.cols = N.cols;eroNums = 0;int mrow, nrow, p, q, t, tp, qcol;int ctemp[MAXROW+1]; //辅助数组//如果Q是非零矩阵if (eroNums * eroNums){for (mrow = 1; mrow <= M.rows; mrow++){//当前行各元素累加器清零for (int x = 1; x <= N.cols; x++){ctemp[x] = 0;}//end_x//当前行的首个非零元素在三元组中的位置为此行前所有非0元素加1Q.rpos[mrow] = eroNums + 1;if (mrow < M.rows){tp = M.rpos[mrow+1];}elsetp = eroNums + 1;for (p = M.rpos[mrow]; p < tp; p++) //对当前行的每个非零元素操作{nrow = M.data[p].c; //在N中找到与M操作元素的c值相等的行值rif (nrow < N.rows){t = N.rpos[nrow+1];}elset = eroNums + 1;//对找出的行的每个非零元素进行操作for (q = N.rpos[nrow]; q < t; q++){qcol = N.data[q].c;//将乘得到的对应值放在相应元素的累加器里面ctemp[qcol] += M.data[p].v * N.data[q].v;}}//p_end_for//对已经求出的累加器中的值压缩到Q中for (qcol = 1; qcol <= Q.cols; qcol++){if (ctemp[qcol])if (++eroNums > MAXSIZE){cout << "Error!" << endl;return 0;}Q.data[eroNums].r = mrow;Q.data[eroNums].c = qcol;Q.data[eroNums].v = ctemp[qcol];}}//qcol_end_for}//arow_end_for}//end_ifcout << "两个稀疏矩阵相乘的结果为:\n";OutputSMatrix(Q);return 1;}//两个稀疏矩阵的加法int AddMatrix(){TSMatrix A, B, C;int i = 1, j = 1, k = 1; //i, j, k分别用以保存A、B、C非零元素个数int value = 0;InputTSMatrix(A, 0);InputTSMatrix(B, 0);if (A.rows != B.rows || A.cols != B.cols){cout << "两个稀疏矩阵的大小不等,不能相加!" << endl;return 0;}if (A.rows == B.rows && A.cols == B.cols){while (i <= eroNums && j <= eroNums){if (A.data[i].r == B.data[j].r){if (A.data[i].c < B.data[j].c){C.data[k].r = A.data[i].r;C.data[k].c = A.data[i].c;C.data[k].v = A.data[i].v;k++;i++;else if (A.data[i].c > B.data[j].c){C.data[k].r = B.data[j].r;C.data[k].c = B.data[j].c;C.data[k].v = B.data[j].v;k++;j++;}else{value = A.data[i].v + B.data[j].v;if (value != 0){C.data[k].r = A.data[i].r;C.data[k].c = A.data[i].c;C.data[k].v = value;k++;}i++;j++;}}//end_ifelse if (A.data[i].r < B.data[j].r){C.data[k].r = A.data[i].r;C.data[k].c = A.data[i].c;C.data[k].v = A.data[i].v;k++;i++;}else{C.data[k].r = B.data[j].r;C.data[k].c = B.data[j].c;C.data[k].v = B.data[j].v;k++;j++;}//把剩余部分元素存入C中if (i > eroNums && j <= eroNums) {for (; j <= eroNums; j++){C.data[k].c = B.data[j].c;C.data[k].v = B.data[j].v;k++;}}if (i <= eroNums && j > eroNums){for (; i <= eroNums; i++){C.data[k].r = A.data[i].r;C.data[k].c = A.data[i].c;C.data[k].v = A.data[i].v;k++;}}}//end_whileC.rows = A.rows;C.cols = A.cols;eroNums = k-1;cout << "输出两个稀疏矩阵的和: " << endl;OutputSMatrix(C);return 1;}//end_ifelsereturn 0;}//两个稀疏矩阵的减法int SubMatrix(){TSMatrix A, B, C;int m = 1, n = 1, k = 1, temp;InputTSMatrix(A, 0);InputTSMatrix(B, 0);C.rows = A.rows;C.cols = A.cols;eroNums = 0;if (A.rows == B.rows && A.cols == B.cols){while (m <= eroNums && n <= eroNums){if (A.data[m].r == B.data[n].r){{temp = A.data[m].v - B.data[n].v;if (temp != 0){C.data[k].r = A.data[m].r;C.data[k].c = A.data[m].c;C.data[k].v = temp;k++;}m++;n++;}else if (A.data[m].c < B.data[n].c){C.data[k].r = A.data[m].r;C.data[k].c = A.data[m].c;C.data[k].v = A.data[m].v;k++;m++;}else{C.data[k].r = B.data[n].r;C.data[k].c = B.data[n].c;C.data[k].v = -B.data[n].v;k++;n++;}}else if (A.data[m].r < B.data[n].r){C.data[k].r = A.data[m].r;C.data[k].c = A.data[m].c;;C.data[k].v = A.data[m].v;k++;m++;}else{C.data[k].r = B.data[n].r;C.data[k].c = B.data[n].c;C.data[k].v = -B.data[n].v;k++;n++;}}//end_whileif (m <= eroNums){for (; m <= eroNums; m++){C.data[k].r = A.data[m].r;C.data[k].c = A.data[m].c;C.data[k].v = A.data[m].v;k++;}}if (n <= eroNums){for (; n <= eroNums; n++){C.data[k].r = B.data[n].r;C.data[k].c = B.data[n].c;C.data[k].v = -B.data[n].v;k++;}}eroNums = k-1;cout << "两个稀疏矩阵的差为:\n";OutputSMatrix(C);return 1;} //end_ifelse{cout << "两个稀疏矩阵的大小不同,不能相减!\n";return 0;}}//得到矩阵元素M[i][j]的值int value(TSMatrix M, int i, int j){int k;for (k = 1; k <= eroNums; k++){if (M.data[k].r == i && M.data[k].c == j){return M.data[k].v;}}return 0;}//矩阵乘法的算法2int MultMat(){TSMatrix A, B, C;InputTSMatrix(A, 0);InputTSMatrix(B, 0);int i, j, k, temp = 0, p = 1;if (A.cols != B.rows){cout << "矩阵A的列数不等于矩阵B的行数不能相乘!\n";return 0;}else{for (i = 1; i <= A.rows; i++){for (j = 1; j <= B.cols; j++){temp = 0;for (k = 1; k <= A.cols; k++){temp += value(A, i, k) * value(B, k, j);}if (temp != 0){C.data[p].r = i;C.data[p].c = j;C.data[p].v = temp;p++;}}}C.rows = A.rows;C.cols = B.cols;eroNums = p-1;OutputSMatrix(C);return 1;}}//计算矩阵的行列式, 通过递归算法来实现int JsMatrix(int s[][MAXROW], int n){int i, j, k, r, total = 0;int b[SIZENUM][SIZENUM]; //b[N][N]用于存放在矩阵s[N][N]中元素s[0]的余之式if (n == 1){total = s[0][0];}else if (n == 2){total = s[0][0] * s[1][1] - s[0][1] * s[1][0];}else{for (i = 0; i < n; i++){for (j = 0; j < n-1; j++){for (k = 0; k < n-1; k++){if (k >= i){b[j][k] = s[j+1][k+1];}else{b[j][k] = s[j+1][k];}}//end_for_k}//end_for_jif (i % 2 == 0){r = s[0][i] * JsMatrix(b, n-1); //递归调用}else{r = (-1) * s[0][i] * JsMatrix(b, n-1);}total += r;}//end_for_i}//end_elsereturn total;}//求原矩阵个元素对应的余之式, 存放在b[n][n]中,定义为float型void N1Matrix(int s[][SIZENUM], float b[][SIZENUM], int n){int i, j, k, l, m, g, a[SIZENUM][SIZENUM];for (i = 0; i < n; i++){m = i;for (j = 0; j < n; j++){g = j;for (k = 0; k < n-1; k++){for (l = 0; l < n-1; l++){if (k >= m && l >= g){a[k][l] = s[k+1][l+1];}else if (k < m && l >= g){a[k][l] = s[k][l+1];}else if (k >= m && l < g){a[k][l] = s[k+1][l];}else{a[k][l] = s[k][l];}}//end_for_l}//end_for_kb[i][j] = JsMatrix(a, n-1);}//end_for_j}//end_for_i}//稀疏矩阵求逆void InverseMat(){TSMatrix M;InputTSMatrix(M, 0);int i, j, k, n = M.rows;float temp;int a[SIZENUM][SIZENUM];float b[SIZENUM][SIZENUM], c[SIZENUM][SIZENUM];for (i = 0; i < n; i++) //初始化矩阵a{for (j = 0; j < n; j++){a[i][j] = 0;}}for (i = 1; i <= eroNums; i++) //给矩阵a赋值{a[M.data[i].r-1][M.data[i].c-1] = M.data[i].v;}cout << "稀疏矩阵对应的普通矩阵为: \n";for (i = 0; i < n; i++) //打印原矩阵{for (j = 0; j < n; j++){cout << setw(4) << a[i][j] << setw(4);}cout << endl;}k = JsMatrix(a, n);cout << "矩阵的行列式值: |A| = " << k << endl;if (k == 0){cout << "行列式的值为0, 原矩阵无逆矩阵!" << endl;}else{N1Matrix(a, b, n); //调用函数,得到原矩阵各元素对应的余之式存放在数组b[n][n]中//求代数余之式cout << "普通矩阵各元素对应的代数余之式矩阵为: \n";for (i = 0; i < n; i++){for (j = 0; j < n; j++){if ((i+j)%2 != 0 && b[i][j] != 0){b[i][j] = -b[i][j];}cout << setw(4) << b[i][j] << setw(4);}cout << endl;}//end_for_i//对b[N][N]转置,此时b[n][n]存放的为原矩阵的伴随矩阵for (i = 0; i < n; i++){for (j = i+1; j < n; j++){temp = b[i][j];b[i][j] = b[j][i];b[j][i] = temp;}}cout << "伴随矩阵A*: " << endl;for (i = 0; i < n; i++) //打印伴随矩阵A*{for (j = 0; j < n; j++){cout << setw(4) << b[i][j] << setw(4);}cout << endl;}for (i = 0; i < n; i++) //求逆矩阵,此时c[n][n]中存放的是原矩阵的逆矩阵{for (j = 0; j < n; j++){c[i][j] = b[i][j]/k;}}cout << "逆矩阵(A*)/|A|: " << endl;for (i = 0; i < n; i++) //打印逆矩阵{for (j = 0; j < n; j++){cout << setw(6) << c[i][j] << setw(6);}cout << endl;}}//end_else}{char c;cout << setw(50) << "******欢迎使用稀疏矩阵的相关操作!******" << endl << endl;cout.fill('*');cout << setw(20) << '*';cout << "请选择要进行的操作";cout << setw(20) << '*' << endl;cout << setw(6) << '*' << " 1: 稀疏矩阵的普通转置算法" << endl;cout << setw(6) << '*' << " 2: 稀疏矩阵的快速转置算法" << endl;cout << setw(6) << '*' << " 3: 稀疏矩阵的乘法的快速算法" << endl;cout << setw(6) << '*' << " 4: 稀疏矩阵的乘法的经典算法" << endl;cout << setw(6) << '*' << " 5: 稀疏矩阵的加法" << endl;cout << setw(6) << '*' << " 6: 稀疏矩阵的减法" << endl;cout << setw(6) << '*' << " 7: 求稀疏矩阵的逆" << endl;cout << setw(6) << '*' << " 0: 退出程序" << endl;cout.fill(' ');c = getchar();switch(c){case '1':TranSMatrix();break;case '2':FastTranMat();break;case '3':MultSMatrix();break;case '4':MultMat();break;case '5':AddMatrix();break;case '6':SubMatrix();break;case '7':InverseMat();break;case '0':cout << "谢谢使用! 再见!" << endl;break;cout << "错误命令!" << endl << endl;break;}return 0;。

稀疏矩阵的运算

稀疏矩阵的运算

数据结构课程设计稀疏矩阵的运算学生姓名:学号:指导教师:完成日期:目录:1、分析问题和确定解决方案 (3)1.1问题描述 (3)1.2 输入的形式和输入值的范围 (3)1.3 输出的形式 (3)1.4 程序所能达到的功能 (3)1.5 测试数据 (3)1.6 确定解决方案 (4)1.7所有抽象数据类型的定义 (4)2、详细设计 (5)2.1稀疏矩阵加法运算思路 (5)2.2稀疏矩阵减法运算思路 (7)2.3稀疏矩阵转置运算思路 (9)2.4创建稀疏矩阵 (11)3、系统调试与测试 (12)3.1程序的菜单界面 (12)3.2 实现加法运算 (12)3.3 实现减法运算 (13)3.4实现转置运算 (14)4、结果分析 (15)4.1、算法的时空分析 (15)4.2、经验和体会 (15)5、参考文献 (15)1、分析问题和确定解决方案1.1问题描述稀疏矩阵是指那些多数元素为零的矩阵。

利用“稀疏”特点进行存储和计算可以大大节省存储空间,提高计算效率。

实现一个能进行稀疏矩阵基本运算的运算器。

用三元组实现稀疏矩阵的相加、相减,转置;1.2输入的形式和输入值的范围以三元组的形式输入,首先应输入矩阵的行数和列数,并判别给出的两个矩阵的行、列数对于所要求作的运算是否相匹配。

可设矩阵的行数和列数均不超过20;例如:输入的三元组为:((1,1,10),(2,3,9),(3,1,-1))其对应的稀疏矩阵为:⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡-0019000010 1.3 输出的形式运算结果的矩阵以通常的阵列形式输出; 1.4程序所能达到的功能该程序可以实现以三元组形式输入两个矩阵,求出两个矩阵的和、差、转置;并可根据输入的矩阵的行列数不同判别是否可以进行相加、减、转置,并重新输入正确的矩阵;1.5测试数据测试的数据及其结果如下:矩阵M 矩阵N 矩阵Q加法:⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡-0019000010 +⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡--301100000 = ⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡-3008000010 减法:⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡-0190010 - ⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡--311000 = ⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡-32100010 转置:⎥⎥⎥⎥⎦⎤⎢⎢⎢⎢⎣⎡-001000000010034 -> ⎥⎥⎥⎥⎥⎦⎤⎢⎢⎢⎢⎢⎣⎡001000000103-0041.6 确定解决方案进入运算器界面后选择要实行的操作,按1实现矩阵相加,调用函数AddRLSMatrix ,若输入的两个矩阵行列数不相等,则提示输入错误,重新输入矩阵进行加法运算;按2实现矩阵相减,若输入的两个矩阵行列数不相等,则提示输入错误,重新输入矩阵进行减法运算;按3实现矩阵的转置;按4退出程序 ; 以加法为例实现运算过程,如下:(稀疏矩阵的和为Q) 第一个稀疏矩阵M 的三元组为((1,1,10),(2,3,9),(3,1,-1)) 第二个稀疏矩阵N 的三元组为((2,3,-1),(3,1,1),(3,3,-3))M 的第一个三元组(1,1,10)与N 的第一个三元组(2,3,-1)比较,因行数1<2则Q 得到第一个三元组(1,1,10);M 的第二个三元组与N 的第一个三元组比较,因对应行列数相等则9+(-1)=8,次行列数就是Q 的行列数即得到Q 的第二个三元组为(2,3,8);M 第三个三元组(3,1,-1))与N 的第二个三元组进行比较,因对应行列数相等,且1+(-1)=0,则不进行相加;而此时只有 N 的第三个三元组(3,3,-3)符合条件,则Q 得到第三个三元组(3,3,-3);最终结果为 ((1,1,10),(2,3,8),(3,3,-3))1.7所有抽象数据类型的定义以顺序存储结构来表示三元组表,则可得到稀疏矩阵的一种压缩存储方式——三元组顺序表。

稀疏矩阵的运算(完美版)

稀疏矩阵的运算(完美版)

专业课程设计I报告(2011 / 2012 学年第二学期)题目稀疏矩阵的转换专业软件工程学生姓名张鹏宇班级学号09003018指导教师张卫丰指导单位计算机学院软件工程系日期2012年6月18号指导教师成绩评定表附件:稀疏矩阵的转换一、课题内容和要求1.问题描述设计程序用十字链表实现稀疏矩阵的加、减、乘、转置。

2.需求分析(1)设计函数建立稀疏矩阵,初始化值。

(2)设计函数输出稀疏矩阵的值。

(3)构造函数进行两个稀疏矩阵相加,输出最终的稀疏矩阵。

(4)构造函数进行两个稀疏矩阵相减,输出最终的稀疏矩阵。

(5)构造函数进行两个稀疏矩阵的相乘,输出最终的稀疏矩阵。

(6)构造函数进行稀疏矩阵的转置,并输出结果。

(7)退出系统。

二、设计思路分析(1)设计函数建立稀疏矩阵,初始化值。

(2)设计函数输出稀疏矩阵的值。

(3)构造函数进行两个稀疏矩阵相加,输出最终的稀疏矩阵。

(4)构造函数进行两个稀疏矩阵相减,输出最终的稀疏矩阵。

(5)构造函数进行两个稀疏矩阵的相乘,输出最终的稀疏矩阵。

(6)构造函数进行稀疏矩阵的转置,并输出结果。

(7)退出系统。

三、概要设计为了实现以上功能,可以从3个方面着手设计。

1.主界面设计为了实现对稀疏矩阵的多种算法功能的管理,首先设计一个含有多个菜单项的主控菜单子程序以链接系统的各项子功能,方便用户交互式使用本系统。

本系统主控菜单运行界面如图所示。

2.存储结构设计本系统采用单链表结构存储稀疏矩阵的具体信息。

其中:全部结点的信息用头结点为指针数组的单链表存储。

3.系统功能设计本系统除了要完成稀疏矩阵的初始化功能外还设置了4个子功能菜单。

稀疏矩阵的初始化由函数i typedef int ElemType 实现。

建立稀疏矩阵用void Creat()实现,依据读入的行数和列数以及非零元素的个数,分别设定每个非零元素的信息。

4个子功能的设计描述如下。

(1)稀疏矩阵的加法:此功能由函数void Xiangjia( )实现,当用户选择该功能,系统即提示用户初始化要进行加法的两个矩阵的信息。

稀疏矩阵完整版

稀疏矩阵完整版

稀疏矩阵运算器:矩阵加、减、乘、快速转置、求逆算法#include<stdio.h>#include<stdlib.h>#include<iostream>#include<iomanip>#include<conio.h>using namespace std;#define maxsize 100#define maxrow 10#define sizenum 10#define OK 1#define ERROR -1typedef struct{int row; //行数int col; //列数int v; //非零元素值}triplenode;typedef struct{triplenode data[maxsize+1]; //非零元三元组int rowtab[maxrow+1];//各行第一个非零元的位置表int mu,nu,tu; //矩阵的行数、列数和非零元个数}rtripletable;void creat(rtripletable &A) //创建稀疏矩阵{int k=1,sum=1,loop,p,t;int num[maxrow+1];cout<<"请输入矩阵的行数和列数:"<<endl;cout<<"行数:";cin>>A.mu;cout<<"列数:";cin>>A.nu;cout<<"非零元素个数:";cin>>A.tu;cout<<"请按行列值的形式输入该矩阵的非零元"<<endl;for(loop=1;loop<=A.tu;loop++){cin>>A.data[loop].row>>A.data[loop].col>>A.data[loop].v;//输入三元组的行数,列数和非零元素值}for(p=1;p<=A.mu;p++) num[p]=0;//A三元组每一列的非零元素个数for(t=1;t<=A.tu;t++) ++num[A.data[t].row];//求A中每一列含非零元个数A.rowtab[1]=1;//求第p列中第一个非零元在A.data中的序号for(t=2;t<=A.mu;t++) A.rowtab[t]=A.rowtab[t-1]+num[t-1];return;}void print(rtripletable A) //输出稀疏矩阵{int result[maxrow+1][maxrow+1];//定义一个二维数组int loop1,loop2;for(loop1=1;loop1<=A.mu;loop1++)for(loop2=1;loop2<=A.nu;loop2++)result[loop1][loop2]=0; //初始化为0for(loop1=1;loop1<=A.tu;loop1++)result[A.data[loop1].row][A.data[loop1].col]=A.data[loop1].v;for(loop1=1;loop1<=A.mu;loop1++){cout<<"|";for(loop2=1;loop2<=A.nu;loop2++)cout<<result[loop1][loop2]<<"";//输出所做运算的结果cout<<"|"<<endl;}}int addsmatrix(rtripletable M, rtripletable N)//矩阵相加{if(M.mu!=N.mu) //行数相等才能相加cout<<"出错";rtripletable Q;Q.mu=M.mu;Q.nu=N.nu;int p,q,k;p=1;q=1;k=1;while(p<=M.tu&&q<=N.tu) //两个稀疏矩阵存在{if(M.data[p].row==N.data[q].row)//两个稀疏矩阵的行数相等{if(M.data[p].col==N.data[q].col)//两个稀疏矩阵的列数相等{if(M.data[p].v+N.data[q].v!=0)//两个稀疏矩阵相加的结果不为0{Q.data[k].row=M.data[p].row;Q.data[k].col=M.data[p].col;Q.data[k].v=M.data[p].v+N.data[q].v;++k;}++q;++p;}else if(M.data[p].col<N.data[q].col)//第一个稀疏矩阵列数小于第二个稀疏矩阵列数{Q.data[k]=M.data[p];//把M中的所有信息都赋给Q++p;++k;}else//第一个稀疏矩阵列数大于第二个稀疏矩阵的列数{Q.data[k]=N.data[q];++q;++k;}}else if(M.data[p].row<N.data[q].row)//第一个稀疏矩阵行列数小于第二个稀疏矩阵行数{Q.data[k]=M.data[p];++p;++k;}else//第一个稀疏矩阵行列数小于第二个稀疏矩阵行数{Q.data[k]=N.data[q];++q;++k;}}while(p<=M.tu) //只有M并且符合条件{Q.data[k]=M.data[p];++p;++k;}while(q<=N.tu) //只有N并且符合条件{Q.data[k]=N.data[q];++q;++k;}Q.tu=k-1;cout<<"加法结果为:"<<endl;print(Q); //调用print()return OK;}int subsmatrix(rtripletable M, rtripletable N) //稀疏矩阵相减{if(M.mu!=N.mu) //行数相等才能相加cout<<"出错";rtripletable Q;Q.mu=M.mu;Q.nu=N.nu;int p,q,k;p=1;q=1;k=1;while(p<=M.tu&&q<=N.tu) //两个稀疏矩阵存在{if(M.data[p].row==N.data[q].row)//两个稀疏矩阵的行数相等{if(M.data[p].col==N.data[q].col)//两个稀疏矩阵的列数相等{if(M.data[p].v-N.data[q].v!=0)//两个稀疏矩阵相减的结果不为0{Q.data[k].row=M.data[p].row;Q.data[k].col=M.data[p].col;Q.data[k].v=M.data[p].v-N.data[q].v;++k;}++q;++p;}if(M.data[p].col<N.data[q].col)//第一个稀疏矩阵列数小于第二个稀疏矩阵的列数{Q.data[k]=M.data[p];++p;++k;}if(M.data[p].col>N.data[q].col)//第一个稀疏矩阵列数大于第二个稀疏矩阵的列{Q.data[k].row=N.data[q].row;Q.data[k].col=N.data[q].col;Q.data[k].v=-N.data[q].v;++q;++k;}if(M.data[p].row<N.data[q].row)//第一个稀疏矩阵行列数小于第二个稀疏矩阵行数{Q.data[k]=M.data[p];++p;++k;}if(M.data[p].row>N.data[q].row)//第一个稀疏矩阵行列数大于第二个稀疏矩阵行数{Q.data[k].row=N.data[q].row;Q.data[k].col=N.data[q].col;Q.data[k].v=-N.data[q].v;++q;++k;}}while(p<=M.tu) //只有M并且符合条件{Q.data[k]=M.data[p];++p;++k;}while(q<=N.tu) //只有N并且符合条件{Q.data[k].row=N.data[q].row;Q.data[k].col=N.data[q].col;Q.data[k].v=-N.data[q].v;++q;++k;}Q.tu=k-1;cout<<"减法结果为:"<<endl;print(Q); //调用print()return OK;}void multsmatrix(rtripletable M, rtripletable N, rtripletable &Q) //稀疏矩阵相乘{int arow,brow;int p,q,tp,t,x;int ccol;int ctemp[maxrow+1]; //定义累加器if(M.nu!=N.mu)return;Q.mu=M.mu;Q.nu=N.nu;Q.tu=0; //Q初始化if(M.tu*N.tu!=0){//Q是非零矩阵for(arow=1;arow<=M.mu;arow++)//处理M的每一行for(x=1;x<=Q.nu;x++) //处理M的每一列ctemp[x]=0; //当前行各元素累加器清零Q.rowtab[arow]=Q.tu+1;if(arow<M.mu) tp=M.rowtab[arow+1];else tp=M.tu+1;for(p=M.rowtab[arow];p<tp;++p)//对当前行中每一个非零元{brow=M.data[p].col; //找到对应元N中的行号if(brow<N.mu) t=N.rowtab[brow+1];else t=N.tu+1;for(q=N.rowtab[brow];q<t;++q){ccol=N.data[q].col; //乘积元素在Q中列数ctemp[ccol]+=M.data[p].v*N.data[q].v;}}//求得Q中第crow(=arow)行的非零元for(ccol=1;ccol<=Q.nu;ccol++)//压缩存储该行非零元{if(ctemp[ccol]){if(++Q.tu>maxsize)return ;Q.data[Q.tu].row=arow; //行数Q.data[Q.tu].col=ccol; //列数Q.data[Q.tu].v=ctemp[ccol];//累加非零元素值}}}}cout<<"乘法结果为:"<<endl;print(Q); //调用print()}int FastTranMat(rtripletable M,rtripletable &Q){int num[maxrow+1]; //表示矩阵M中第col列非零元素的个数int cpot[maxrow+1]; //表示矩阵M中第col列第一个非0元素在b.data中的位置int p, q, col, t;Q.mu = M.mu;Q.nu = M.nu;Q.tu = M.tu;{for (col = 1; col <= M.nu; col++)//M中各列元素初始化{num[col] = 0;}for (t = 1; t <= M.tu; t++){++num[M.data[t].col]; //求M中每一列非零元个数}//求第col列第一个非零元在b.data中的序号cpot[1] = 1;for (col = 2; col <= M.nu; col++){cpot[col] = cpot[col-1] + num[col-1];}for (p = 1; p <= M.tu; p++){col = M.data[p].col; //稀疏矩阵M中每个元素对应的列号q = cpot[col]; //稀疏矩阵M中第一个非零元素位置Q.data[q].row = M.data[p].col;Q.data[q].col = M.data[p].row;Q.data[q].v = M.data[p].v;++cpot[col];}//end_for}//end_ifcout <<"运用快速算法,输入矩阵的转置为: "<< endl;print(Q);return OK;}int JsMatrix(int s[][maxrow], int n){int i, j, k, r, total = 0;int b[sizenum][sizenum]; //b[N][N]用于存放在矩阵s[N][N]中元素s[0]的余之式if (n == 1){total = s[0][0];}else if (n == 2){total = s[0][0] * s[1][1] - s[0][1] * s[1][0];else{for (i = 0; i < n; i++){for (j = 0; j < n-1; j++){for (k = 0; k < n-1; k++){if (k >= i){b[j][k] = s[j+1][k+1];}else{b[j][k] = s[j+1][k];}}//end_for_k}//end_for_jif (i % 2 == 0){r = s[0][i] * JsMatrix(b, n-1); //递归调用}else{r = (-1) * s[0][i] * JsMatrix(b, n-1);}total += r;}//end_for_i}//end_elsereturn total;}//求原矩阵个元素对应的余之式, 存放在b[n][n]中,定义为float型void N1Matrix(int s[][sizenum], float b[][sizenum], int n) {int i, j, k, l, m, g, a[sizenum][sizenum];for (i = 0; i < n; i++){m = i;for (j = 0; j < n; j++){g = j;for (k = 0; k < n-1; k++)for (l = 0; l < n-1; l++){if (k >= m && l >= g){a[k][l] = s[k+1][l+1];}else if (k < m && l >= g){a[k][l] = s[k][l+1];}else if (k >= m && l < g){a[k][l] = s[k+1][l];}else{a[k][l] = s[k][l];}}//end_for_l}//end_for_kb[i][j] = JsMatrix(a, n-1);}//end_for_j}//end_for_i}//稀疏矩阵求逆void InverseMat(rtripletable M,rtripletable &Q) {int i, j, k, n = M.mu;float temp;int a[sizenum][sizenum];float b[sizenum][sizenum], c[sizenum][sizenum];for (i = 0; i < n; i++) //初始化矩阵a{for (j = 0; j < n; j++){a[i][j] = 0;}}for (i = 1; i <= M.tu; i++) //给矩阵a赋值{a[M.data[i].row-1][M.data[i].col-1] = M.data[i].v; }cout <<"稀疏矩阵对应的普通矩阵为: \n";print(M);k = JsMatrix(a, n);cout <<"矩阵的行列式值: |A| = "<< k << endl;if (k == 0){cout <<"行列式的值为0, 原矩阵无逆矩阵!"<< endl;}else{N1Matrix(a, b, n); //调用函数,得到原矩阵各元素对应的余之式存放在数组b[n][n]中//求代数余之式cout <<"普通矩阵各元素对应的代数余之式矩阵为: \n";for (i = 0; i < n; i++){for (j = 0; j < n; j++){if ((i+j)%2 != 0 && b[i][j] != 0){b[i][j] =-b[i][j];}for (i = 0; i < n; i++){printf("|");for (j = 0; j < n; j++){printf("%f ");}//end_for_i//对b[N][N]转置,此时b[n][n]存放的为原矩阵的伴随矩阵for (i = 0; i < n; i++){for (j = i+1; j < n; j++){temp = b[i][j];b[i][j] = b[j][i];b[j][i] = temp;}}cout <<"伴随矩阵A*: "<< endl;for (i = 0; i < n; i++) //打印伴随矩阵A*{printf("|");for (j = 0; j < n; j++){printf("%f ");}printf("|");cout << endl;}for (i = 0; i < n; i++) //求逆矩阵,此时c[n][n]中存放的是原矩阵的逆矩阵{for (j = 0; j < n; j++){c[i][j] = b[i][j]/k;}}cout <<"逆矩阵(A*)/|A|: "<< endl;for (i = 0; i < n; i++) //打印逆矩阵{for (j = 0; j < n; j++){cout << setw(6) << c[i][j] << setw(6);}cout << endl;}}//end_else}void main(){char choice;rtripletable A,B,Q;cout<<"|*****欢迎使用稀疏矩阵运算器******| \n";cout<<"\n A、输入矩阵1 \n";cout<<"\n B、输入矩阵2 \n";cout<<"\n C、矩阵相加 \n";cout<<"\n D、矩阵相减 \n";cout<<"\n E、矩阵相乘 \n";cout<<"\n F、矩阵转置 \n";cout<<"\n G、矩阵求逆 \n";cout<<"\n H、退出本系统 \n";cout<<"请选择所需要的操作功能(A,B,C,D,E,F,G,H):";do{cin>>choice;switch(choice){case'A':creat(A);break;case'B':creat(B);break;case'C':addsmatrix(A,B);break;case'D':subsmatrix(A,B);break;case'E':multsmatrix(A,B,Q);break;case'F':creat(A);FastTranMat(A,Q);break;case'G':creat(A);InverseMat(rtripletable M,rtripletable &Q);break;}cout<<"请选择所需要的操作功能(A,B,C,D,E,F,G,H):";}while(1);}}。

稀疏矩阵的压缩存储及运算

稀疏矩阵的压缩存储及运算

稀疏矩阵的压缩存储及运算一、实验内容实现稀疏矩阵的压缩存储方法以及在特定存储方法下的基本运算二、实验母的掌握数组的应用,包括稀疏矩阵、特殊矩阵的压缩存储方法。

矩阵的基本运算的实现,包括矩阵相加、转置、乘法等。

三、问题描述1)用行逻辑链接顺序表和十字链表分别实现稀疏矩阵的压缩存储2)编程实现矩阵的转置运算和乘法运算(运用行逻辑链接顺序表或十字链表作为存储结构)四、问题的实现稀疏矩阵的抽象数据类型定义:ADT SpareseMatrix{数据对象:;,,2,1;,,2,1|{n j m i D a ij ===},,列数分别称为矩阵的行数和和n m ElemSet a j i ∈数据关系: :}1,11|,{}11,1|,{},{,1,1,,n j m i Col n j m i Row Col Row R a a a a j i j i j i j i ≤≤-≤≤><=-≤≤≤≤><==++基本操作:CreateSMatrix(&M);操作结果:创建稀疏矩阵M 。

PrintSMatrix(M);初始条件:稀疏矩阵M 存在。

操作结果:输出稀疏矩阵M 。

AddSMatrix(M ,N ,&Q);初始条件:稀疏矩阵M 和N 的行数和列数对应相等。

操作结果:求稀疏矩阵的和Q=M+N 。

MultSMatrix(M ,N ,&Q);初始条件:稀疏矩阵M 的列数等于N 的行数。

操作结果:求稀疏矩阵乘积Q=M*N 。

TransposeSMatrix(M,&T);初始条件:稀疏矩阵M 存在。

操作结果:求稀疏矩阵M 的转置矩阵T 。

}ADT SpareseMatrix五、主要源程序代码#include <iostream>using namespace std;#define MAXSIZE 100;typedef struct OLNode{int i,j;int e;struct OLNode *right,*down;}OLNode,*OLink;typedef struct{OLink *rhead,*chead;int mu,nu,tu;}CrossList; //十字链表结构体定义int CreatSMatrix_OL(CrossList &M){int i,j,e;OLink q;OLink p;cout<<"请输入稀疏矩阵的行数,列数,非零元素的个数:";cin>>M.mu;cin>>M.nu;cin>>M.tu;M.rhead=(OLink *)malloc((M.mu+1)*sizeof(OLNode));M.chead=(OLink *)malloc((M.nu+1)*sizeof(OLNode));for(i=1;i<=M.mu;i++) M.rhead[i]=NULL;for(i=1;i<=M.nu;i++) M.chead[i]=NULL;cout<<"请输入稀疏矩阵,若为空,则退出"<<endl;cin>>i;cin>>j;cin>>e;while (i!=0){p=(OLink)malloc(sizeof(OLNode));p->i=i;p->j=j;p->e=e;if (M.rhead[i]==NULL || M.rhead[i]->j>j) {p->right=M.rhead[i];M.rhead[i]=p;}else{q=M.rhead[i];while (q->right && q->right->j<j)q=q->right;p->right=q->right;q->right=p;}if (M.chead[j]==NULL || M.chead[j]->i>i) {p->down=M.chead[j];M.chead[j]=p;}else{q=M.chead[j];while (q->down && q->down->i<i)q=q->down;p->down=q->down;q->down=p;}cin>>i;cin>>j;cin>>e;}} //创建十字链表void TurnSMatrix_OL(CrossList &M){int a,b;OLink p,q;for(a<1;a<=M.mu;a++){q=p=M.rhead[a];while(q){b=p->i;p->i=p->j;p->j=b;q=p->right;p->right=p->down;p->down=q;}}} //十字链表实现稀疏矩阵转置int AddSMatrix_OL(CrossList *A,CrossList *B){OLNode *pa,*pb,*p,*pre,*cp[100];int i,j,t;t=A->tu+B->tu;for(j=1;j<=A->nu;j++) cp[j]=A->chead[j];for(i=1;i<=A->mu;i++){pa=A->rhead[i];pb=B->rhead[i];pre=NULL;while(pb){if(pa==NULL || pa->j>pb->j){p=(OLink)malloc(sizeof(OLNode));if(!pre)A->rhead[i]=p;else pre->right=p;p->right=pa;pre=p;p->i=i;p->j=pb->j;p->e=pb->e;if(!A->chead[p->j]){A->chead[p->j]=cp[p->j]=p;p->down=NULL;}else{cp[p->j]->down=p;cp[p->j]=p;}pb=pb->right;}else if(pa->j<pb->j) {pre=pa;pa=pa->right;}else if(pa->e+pb->e){t--;pa->e+=pb->e;pre=pa;pa=pa->right;pb=pb->right;}else{t=t-2;if(!pre)A->rhead[i]=pa->right;else pre->right=pa->right;p=pa;pa=pa->right;if(A->chead[p->j]==p) A->chead[p->j]=cp[p->j]=p->down;else cp[p->j]->down=p->down;free(p);pb=pb->right;}}}A->mu=A->mu>B->mu? A->mu:B->mu;A->nu=A->nu>B->nu? A->nu:B->nu;return 1;} //十字链表实现两稀疏矩阵相加int MultSMatrix_OL(CrossList M,CrossList N,CrossList &Q){int i,j,e;OLink p0,q0,p,p1,p1a;if(M.nu!=N.mu){cout<<"稀疏矩阵A的列数和B的行数不相等,不能相乘";return 0;}Q.mu=M.mu;Q.nu=N.nu;Q.tu=0;if(!(Q.rhead=(OLink *)malloc((Q.mu+1)*sizeof(OLink))))exit(-2);if(!(Q.chead=(OLink *)malloc((Q.nu+1)*sizeof(OLink))))exit(-2);for(i=1;i<=Q.mu;i++) Q.rhead[i]=NULL;for(i=1;i<=Q.nu;i++) Q.chead[i]=NULL;for(i=1;i<=Q.mu;i++)for(j=1;j<=Q.nu;j++){p0=M.rhead[i];q0=N.chead[j];e=0;while(p0 && q0){if(p0->j>q0->i) q0=q0->down;else if(p0->j<q0->i) p0=p0->right;else{e+=p0->e*q0->e;q0=q0->down;p0=p0->right;}}if(e){if(!(p=(OLink)malloc(sizeof(OLNode))))exit(-2);Q.tu++;p->i=i;p->j=j;p->e=e;p->right=NULL;p->down=NULL;if(Q.rhead[i]==NULL)Q.rhead[i]=p1=p;else p1->right=p;p1=p;if(Q.chead[j]==NULL)Q.chead[j]=p;else{p1a=Q.chead[j];while(p1a->down)p1a=p1a->down;p1a->down=p;}}}return 1;} //十字链表实现两稀疏矩阵相乘int ShowSMatrix(CrossList *A){int a;OLink p;for(a=1;a<=A->mu;a++)if(A->rhead[a]) {p=A->rhead[a];}while(p){printf("%3d%3d%3d\n",p->i,p->j,p->e);p=p->right;}return 1;} //十字链表显示void main(){int n;char c;CrossList MM,TT,SS;CreatSMatrix_OL(MM);cout<<"您输入的稀疏矩阵(只列出非零元素):"<<endl;cout<<"行列大小"<<endl;ShowSMatrix(&MM);cout<<"请选择操作:"<<endl;cout<<"1:实现稀疏矩阵的转置"<<endl;cout<<"2:实现两稀疏矩阵的相加"<<endl;cout<<"3:实现两稀疏矩阵的相乘"<<endl;cout<<"4:退出程序"<<endl;cin>>n;switch(n){case 1:TurnSMatrix_OL(MM);cout<<"转置后的稀疏矩阵:行列大小"<<endl;ShowSMatrix(&MM);break;case 2:cout<<"请输入另一个稀疏矩阵:"<<endl;CreatSMatrix_OL(TT);AddSMatrix_OL(&MM,&TT);cout<<"相加后的矩阵为:"<<endl;ShowSMatrix(&MM);break;case 3:cout<<"请输入另一个稀疏矩阵:"<<endl;CreatSMatrix_OL(TT);MultSMatrix_OL(MM,TT,SS);cout<<"相乘后的矩阵为:"<<endl;ShowSMatrix(&SS);break;case 4:exit(0);default:cout<<"error!"<<endl;}system("pause");}六、总结整个实验中学会了稀疏矩阵的压缩存储方法,用十字链表来存储,以及在特定存储方法下的基本运算。

稀疏矩阵的压缩计算

稀疏矩阵的压缩计算

稀疏矩阵的压缩计算稀疏矩阵是指矩阵中绝大多数元素都是0的矩阵,即非零元素远小于矩阵元素总数的矩阵。

在实际应用中,稀疏矩阵非常常见,比如图像处理、自然语言处理、推荐系统等领域的数据处理。

但是由于稀疏矩阵的特殊性,其存储和计算都会带来额外的开销。

因此,稀疏矩阵的压缩计算变得至关重要。

为了有效地存储和计算稀疏矩阵,研究者提出了多种压缩算法,其中最常用的有三种:压缩行(CSR)、压缩列(CSC)和亚正规(ELL)压缩算法。

压缩行(CSR)算法将稀疏矩阵的每行非零元素及其列索引存储在两个数组中。

一个数组用于存储每行第一个非零元素在第二个数组中的索引位置,第二个数组按非零元素出现的顺序存储矩阵的非零元素值和对应的列索引。

这种方式的好处是能够高效地进行矩阵向量乘法运算,但是在进行矩阵转置和矩阵矩阵相乘时效率较低。

压缩列(CSC)算法与压缩行算法类似,不同之处在于将矩阵的每列非零元素及其行索引存储在两个数组中。

这种方式适用于矩阵转置和矩阵矩阵相乘等操作,但是在矩阵向量乘法中效率较低。

亚正规(ELL)压缩算法综合了压缩行和压缩列算法的优点,将稀疏矩阵的每行的非零元素及其列索引存储在两个二维数组中。

第一个二维数组用于存储每行非零元素的值,第二个二维数组用于存储每行非零元素的列索引。

由于每行的非零元素个数可能不同,因此需要对二维数组进行补齐。

这种方式能够高效地进行矩阵向量乘法和矩阵转置,但是对于矩阵矩阵相乘效率较低。

除了上述的三种压缩算法,还有其他一些针对特定稀疏矩阵特点的压缩算法,如对角线压缩(DIA)算法,将矩阵的对角线及其对应的值存储在数组中,适用于具有对角线分布特点的矩阵;块压缩(BSC)算法,将矩阵按照行或列分块存储在多个数组中,适用于矩阵具有块状结构的情况。

总结来说,稀疏矩阵压缩计算是应对稀疏矩阵存储和计算的重要方法。

通过选择合适的压缩算法,可以充分利用稀疏矩阵的特点,减少存储开销和计算复杂度,提高计算效率。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

专业课程设计I报告( 2011 / 2012 学年第二学期)题目稀疏矩阵的转换专业软件工程学生姓名张鹏宇班级学号 09003018指导教师张卫丰指导单位计算机学院软件工程系日期 2012年6月18号指导教师成绩评定表附件:稀疏矩阵的转换一、课题内容和要求1.问题描述设计程序用十字链表实现稀疏矩阵的加、减、乘、转置。

2.需求分析(1)设计函数建立稀疏矩阵,初始化值。

(2)设计函数输出稀疏矩阵的值。

(3)构造函数进行两个稀疏矩阵相加,输出最终的稀疏矩阵。

(4)构造函数进行两个稀疏矩阵相减,输出最终的稀疏矩阵。

(5)构造函数进行两个稀疏矩阵的相乘,输出最终的稀疏矩阵。

(6)构造函数进行稀疏矩阵的转置,并输出结果。

(7)退出系统。

二、设计思路分析(1)设计函数建立稀疏矩阵,初始化值。

(2)设计函数输出稀疏矩阵的值。

(3)构造函数进行两个稀疏矩阵相加,输出最终的稀疏矩阵。

(4)构造函数进行两个稀疏矩阵相减,输出最终的稀疏矩阵。

(5)构造函数进行两个稀疏矩阵的相乘,输出最终的稀疏矩阵。

(6)构造函数进行稀疏矩阵的转置,并输出结果。

(7)退出系统。

三、概要设计为了实现以上功能,可以从3个方面着手设计。

1.主界面设计为了实现对稀疏矩阵的多种算法功能的管理,首先设计一个含有多个菜单项的主控菜单子程序以链接系统的各项子功能,方便用户交互式使用本系统。

本系统主控菜单运行界面如图所示。

2.存储结构设计本系统采用单链表结构存储稀疏矩阵的具体信息。

其中:全部结点的信息用头结点为指针数组的单链表存储。

3.系统功能设计本系统除了要完成稀疏矩阵的初始化功能外还设置了4个子功能菜单。

稀疏矩阵的初始化由函数i typedef int ElemType 实现。

建立稀疏矩阵用void Creat()实现,依据读入的行数和列数以及非零元素的个数,分别设定每个非零元素的信息。

4个子功能的设计描述如下。

(1)稀疏矩阵的加法:此功能由函数void Xiangjia( )实现,当用户选择该功能,系统即提示用户初始化要进行加法的两个矩阵的信息。

然后进行加法,最后输出结果。

(2)稀疏矩阵的乘法:此功能由函数void Xiangcheng( )实现。

当用户选择该功能,系统提示输入要进行相乘的两个矩阵的详细信息。

然后进行相乘,最后得到结果。

(3)稀疏矩阵的转置:此功能由函数void Zhuanzhi( )实现。

当用户选择该功能,系统提示用户初始化一个矩阵,然后进行转置,最终输出结果。

(4)退出:即退出稀疏矩阵的应用系统。

由函数5实现,但用户选择此功能时,系统会提示你是否确实想退出,如果是,则退出,否则继续。

三、模块设计1.模块设计本程序包含1个模块:主程序模块加各功能实现模块。

2.系统子程序及功能设计本系统共设置7个子程序,各子程序的函数名及功能说明如下。

(1)typedef int ElemType // 初始化矩阵( 2 ) void Creat(TSMatrix &M) //建立矩阵(3)void Print_SMatrix(TSMatrix M) // 输出矩阵的信息以下编号(4)-(6)是稀疏矩阵的基本操作。

依次是:相加,相乘,转置等。

(4)void Xiangjia(TSMatrix A,TSMatrix B,TSMatrix &C,int n)//把A 和B两个矩阵相加,结果是C(5)void Xiangcheng(TSMatrix A,TSMatrix B,TSMatrix &Q)//把A和B两个矩阵相乘,结果是Q(6)void Zhuanzhi(TSMatrix *a,TSMatrix *b)// 把A转置(7)void main()// 主函数。

设定界面的颜色,大小和窗口的标题,调用工作区模块函数四、详细设计#include<stdio.h>#include<malloc.h>#include<stdlib.h>#define MAXSIZE 40 //假设非零元素个数的最大值为40#define MAXRC 20 //假设矩阵的最大行数为20typedef int ElemType;typedef struct{int i,j; //非零元的行下标和列下标ElemType e; //非零元的值}Triple;typedef struct{Triple data[MAXSIZE+1];int rpos[MAXRC+1]; //各行第一个非零元在三元组的位置表int hs,ls,fls;}TSMatrix,*Matrix;void Creat(TSMatrix &M){int i,k;for(i=1;i<=MAXRC+1;i++)M.rpos[i]=0;printf("请输入矩阵的行数、列数和非零元个数(以空格隔开):");scanf("%d %d %d",&M.hs,&M.ls,&M.fls);for(i=1;i<=M.fls;i++){printf("请用三元组形式输入矩阵的元素(行列非零元素):");scanf("%d %d %d",&M.data[i].i,&M.data[i].j,&M.data[i].e);}for(i=1,k=1;i<=M.hs;i++){M.rpos[i]=k;while(M.data[k].i<=i && k<=M.fls)k++;}}void Xiangjia(TSMatrix A,TSMatrix B,TSMatrix &C,int n){int a,b,temp,l;C.hs=A.hs;C.ls=A.ls;a=b=l=1;while(a<=A.fls && b<=B.fls){if(A.data[a].i==B.data[b].i){if(A.data[a].j<B.data[b].j)C.data[l++]=A.data[a++];else if(A.data[a].j>B.data[b].j){C.data[l]=B.data[b]; C.data[l++].e=n*B.data[b++].e;}else{temp=A.data[a].e+n*B.data[b].e;if(temp){C.data[l]=A.data[a];C.data[l].e=temp;l++;}a++;b++;}}else if(A.data[a].i<B.data[b].i)C.data[l++]=A.data[a++];else {C.data[l]=B.data[b];C.data[l++].e=n*B.data[b++].e;}}while(a<=A.fls)C.data[l++]=A.data[a++];while(b<=B.fls){C.data[l]=B.data[b]; C.data[l++].e=n*B.data[b++].e;}C.fls=l-1;}int Xiangcheng(TSMatrix A,TSMatrix B,TSMatrix &Q){int arow,brow,ccol,tp,p,q,t;int ctemp[MAXRC+1];if(A.ls!=B.hs) return 0;Q.hs=A.hs;Q.ls=B.ls;Q.fls=0;if(A.fls*B.fls){for(arow=1;arow<=A.hs;arow++){for(ccol=1;ccol<=Q.ls;ccol++)ctemp[ccol]=0;Q.rpos[arow]=Q.fls+1;if(arow<A.hs) tp=A.rpos[arow+1];else tp=A.fls+1;for(p=A.rpos[arow];p<tp;p++){brow=A.data[p].j;if(brow<B.hs) t=B.rpos[brow+1];else t=B.fls+1;for(q=B.rpos[brow];q<t;q++){ccol=B.data[q].j;ctemp[ccol]+=A.data[p].e*B.data[q].e;}}for(ccol=1;ccol<=Q.ls;ccol++){if(ctemp[ccol]){if(++Q.fls>MAXSIZE) return 0;Q.data[Q.fls].i=arow;Q.data[Q.fls].j=ccol;Q.data[Q.fls].e=ctemp[ccol];}}}}return 1;}void Print_SMatrix(TSMatrix M){int k,l,n;Matrix p;p=&M;for(k=1,n=1;k<=p->hs;k++){for(l=1;l<=p->ls;l++){if(p->data[n].i==k && p->data[n].j==l){printf("%5d",p->data[n].e);n++;}elseprintf("%5d",0);}printf("\n");}printf("\n");}void Zhuanzhi(TSMatrix *a,TSMatrix *b){int q,col,p;b->hs=a->ls;b->ls=a->hs;b->fls=a->fls;if(b->fls){q=1;for(col=1;col<=a->ls;col++)for(p=1;p<=a->fls;p++)if(a->data[p].j==col){b->data[q].i=a->data[p].j;b->data[q].j=a->data[p].i;b->data[q].e=a->data[p].e;++q;}}}void Destory_SMatrix(TSMatrix &M){M.hs=M.ls=M.fls=0;}void main(){TSMatrix A,B,C;TSMatrix *p=&A,*q=&B;int flag,n;while(1){system("cls");printf("\n\n\n");printf("\t┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n");printf("\t┃ *** 稀疏矩阵的加、减、转、乘 *** ┃\n");printf("\t┣━━━━━━━━━━━━━━━━━━━━━━━━━━━┫\n");printf("\t┃1、稀疏矩阵的加法┃\n");printf("\t┃ 2、稀疏矩阵的减法┃\n");printf("\t┃3、稀疏矩阵的转置┃\n");printf("\t┃4、稀疏矩阵的乘法┃\n");printf("\t┃5、退出该应用程序┃\n");printf("\t┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n");printf("输入要进行的项目的编号:");scanf("%d",&flag);if(flag==5) break;Creat(A);printf("矩阵A:\n"); Print_SMatrix(A);switch(flag){case 1: C reat(B);n=1;printf("矩阵B:\n");Print_SMatrix(B);if(A.hs==B.hs && A.ls==B.ls){printf("A+B:\n");Xiangjia(A,B,C,n);Print_SMatrix(C);}else printf("错误!行列不一致\n");break;case 2: Creat(B);n=-1;printf("矩阵B:\n");Print_SMatrix(B);if(A.hs==B.hs && A.ls==B.ls){printf("A-B:\n");Xiangjia(A,B,C,n);Print_SMatrix(C);}else printf("错误!行列不一致\n");break;case 3: printf("A->B:\n");Zhuanzhi(p,q);Print_SMatrix(B);break;case 4: C reat(B);printf("矩阵B:\n");Print_SMatrix(B);printf("A*B:\n");n=Xiangcheng(A,B,C);if(!n) printf("错误!行列不匹配\n");else Print_SMatrix(C);break;default: printf("输入错误!\n");}Destory_SMatrix(A);Destory_SMatrix(B);Destory_SMatrix(C);getchar();getchar();}printf("\n\t\t\t ***程序已经退出***\n");getchar();}五、测试数据及其结果分析六、调试过程中的问题在进行int Xiangcheng(TSMatrix A,TSMatrix B,TSMatrix &Q) 函数调用的时候进行运算的时候出现了一点小差错。

相关文档
最新文档