稀疏矩阵的乘法实现
java 稀疏矩阵三元组乘法

java 稀疏矩阵三元组乘法Java 稀疏矩阵三元组乘法是一种高效的算法,用于处理大型稀疏矩阵的乘法计算。
它的实现原理是将稀疏矩阵用三元组表示,然后对两个矩阵的三元组进行遍历,找到相应的元素进行乘法运算,最后将结果存储在一个新的三元组中。
下面将详细介绍该算法的实现过程以及代码实现。
1. 稀疏矩阵的三元组表示稀疏矩阵是指元素中绝大多数为零的矩阵,只有少数非零元素。
稀疏矩阵的三元组表示将矩阵中的非零元素的行列坐标和元素值用三元组表示出来,便于进行运算。
下面是一个5x5的稀疏矩阵的三元组表示:(0,3,5)(1,1,9)(2,2,8)(3,0,6)(3,1,7)(4,3,3)其中每个三元组表示矩阵中的一行,分别表示非零元素所在的行、列和元素值。
这样,对于任意大小的稀疏矩阵,都可以用三元组表示出来。
2. 三元组乘法实现过程三元组乘法的实现过程如下:首先,需要对两个矩阵的三元组进行遍历,找到行、列坐标相同的元素,然后进行乘法运算并将结果保存在一个新的三元组中。
例如,有两个5x5的稀疏矩阵A和B,它们的三元组分别为:A:(0,3,5)(1,1,9)(2,2,8)(3,0,6)(3,1,7)(4,3,3)B:(0,2,2)(1,2,5)(2,1,3)(3,0,8)(3,3,7)其中A和B的维度必须满足A的列数等于B的行数,也就是5。
对于A和B的乘法,需要遍历A和B的三元组,找到相应的元素进行乘法运算,并将结果保存在一个新的三元组中。
因此,新的三元组的行数等于A的行数,列数等于B的列数,即5x5。
以A的第一行为例,需要遍历B的每一列,找到行列坐标相同的元素进行乘法运算,最后将结果相加得到新矩阵的第一行第二列元素。
重复以上步骤,得到新矩阵的所有元素。
3. Java 代码实现以下是 Java 代码实现稀疏矩阵三元组乘法的实现代码:public class SparseMatrixMultiplication {public static int[][] multiply(int[][] A, int[][] B) {int m = A.length, n = A[0].length, nB = B[0].length; int[][] C = new int[m][nB];List[] indexA = new List[m];for (int i = 0; i < m; i++) {List<Integer> numsA = new ArrayList<>();for (int j = 0; j < n; j++) {if (A[i][j] != 0) {numsA.add(j);numsA.add(A[i][j]);}}indexA[i] = numsA;}for (int i = 0; i < m; i++) {List<Integer> numsA = indexA[i];for (int p = 0; p < numsA.size() - 1; p += 2) {int colA = numsA.get(p);int valA = numsA.get(p + 1);for (int j = 0; j < nB; j++) {int valB = B[colA][j];if (valB != 0)C[i][j] += valA * valB;}}}return C;}}该代码中使用了一个List数组来存储稀疏矩阵A的三元组,便于遍历,提高算法效率。
用十字链表和一般方法分别实现稀疏矩阵的乘法和加法

#include<stdio.h>#include<malloc.h>#define Size 2501# define Size1 51typedef struct{int i;int j;int e;//非零元的值}triple; //定义三元组typedef struct{triple data[Size+1];//矩阵中的元素int rops[Size1+1];// rops[i]为第i行元素中的首非零元在data[]中的序号int mu;//行数int nu;//列数int tu;//非零元数} juzhen;//定义矩阵typedef struct node// 定义十字链表元素{int i,j,e;struct node *right,*down;// 该非零元所在行表和列表的后继元素}node,*link;typedef struct // 定义十字链表对象结构体{link *rhead,*chead;//行和列的头指针int m,n,t;// 系数矩阵的行数,列数,和非零元素个数}crosslist;void createcross(crosslist &M)//建立十字链表{int i,j,e,k;node *p,*q;printf("输入行,列和非零元数,空格隔开:\n");scanf("%d %d %d",&M.m,&M.n,&M.t);M.rhead=(link *)malloc((M.m+1)*sizeof(link));//给行和列的头指针分配内存M.chead=(link *)malloc((M.n+1)*sizeof(link));for(k=1;k<=M.m;k++)//初始化行,列的头指针M.rhead[k]=NULL;for(k=1;k<=M.n;k++)M.chead[k]=NULL;printf("输入非零元的行,列和值,空格隔开:\n");for(k=1;k<=M.t;k++)//输入非零元{scanf("%d %d %d",&i,&j,&e);p=(node *)malloc(sizeof(node));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{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->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;}}}void printcross(crosslist A)//输出十字链表{if(A.m==0)printf("十字链表为空!\n");else{printf("十字链表为:\n");int i,j;for(i=1;i<=A.m;i++){link p=A.rhead[i];for(j=1;j<=A.n;j++){if((p)&&(j==p->j)){printf("%5d",p->e);p=p->right; }elseprintf("%5d",0);}printf("\n");}}printf("\n");}crosslist addcross(){printf("十字链表加法:\n");crosslist a,b;// 创建两个十字链表对象,并初始化createcross(a);createcross(b);node *pre,*h[51],*pa,*pb,*q;//定义辅助指针,pa,pb分别为a,b当前比较的元素,pre为pa的前驱元素int i,j,k=0,m,n; //h[j]指向j列的当前插入位置if(a.m!=b.m||a.n!=b.n)printf("格式不对,不能相加!\n");else{for(i=1;i<=a.m;i++){pa=a.rhead[i];pb=b.rhead[i];pre=NULL;for(j=1;j<=a.n;j++)h[j]=NULL;while(pb){p=(node *)malloc(sizeof(node)); // 开辟新节点,存储b中取出的元素p->i=pb->i;p->j=pb->j;p->e=pb->e;if(pa==NULL||pa->j>pb->j)//当a此行已经检查完或者pb因该放在pa前面{if (pre==NULL)a. rhead[p->i]=p;elsepre->right=p;p->right=pa;pre=p;if (h[p->j]==NULL)//当前插入位置下面无非零元//因为是逐行处理,so,h[p->j],依次下移//因此每次都是指向插入的位置{a. chead [p->j]= p;p->down = NULL;}else{p->down = h[p->j]->down;h[p->j]->down = p;}h[p->j]=p;//*******h[p->j]下移指向下次插入的位置pb=pb->right;//pb指向该行下个元素}else if((pa&&pa->j<pb->j))//只要移动pa的指针****先不加||(pb==NULL&&pa){pre = pa;h[pa->j]=pa;//移动h[],使其指向下次插入的位置pa = pa->right;}else if(pa->j==pb->j){pa->e+=pb->e;if(pa->e)//不为零{pre=pa;h[pa->j]=pa;pb=pb->right;//加else//pa->e为零,删除节点{if (pre ==NULL)a.rhead [pa->i]=pa->right;else{pre->right=pa->right;}p=pa;//p指向pa,用来在下面修改列指针pa=pa->right;if (h [p->j]==NULL)a.chead [p->j]=p->down;else{h[p->j]->down=p->down;}free(p);pb=pb->right;}}}}}return a;}void multycross(crosslist &c)//十字链表乘法{node *p,*q,*u,*v,*p1,*p2;crosslist a,b;link *r;int i,j,k,e;printf("十字链表乘法:\n");createcross(a);createcross(b);if(a.n!=b.m)printf("格式错误,不能相乘!\n");else{c.m=a.m;c.n=b.n;c.t=0;c.rhead=(link *)malloc((a.m+1)*sizeof(link));//给行和列的头指针分配内存c.chead=(link *)malloc((b.n+1)*sizeof(link));for(k=1;k<=a.m;k++)//初始化行,列的头指针c.rhead[k]=NULL;for(k=1;k<=b.n;k++)c.chead[k]=NULL;r=(link *)malloc((b.n+1)*sizeof(link));for(i=1;i<=a.m;i++){u=(node *)malloc(sizeof(node));u->e=0;u->i=0;u->j=0;for(k=1;k<=b.n;k++)//初始化r[]r[k]=u;p1=p=a.rhead[i];for(j=1;j<=b.n;j++){p=p1;q=b.chead[j];v=(node *)malloc(sizeof(node));//初始化v,v为将插入c矩阵的元素v->e=0;v->i=i;v->j=j;while(p&&q){if(p->j>q->i)q=q->down;else if(p->j<q->i)p=p->right;else{v->e+=p->e*q->e;p=p->right;q=q->down;}}if(v->e)//如果不为零,则插入c矩阵中{//同建立十字链表if(c.rhead[i]==NULL||c.rhead[i]->j>j)//插入元素所在行无非零元或首非零元的列标大于插入元素的列标{v->right=c.rhead[i];c.rhead[i]=v;}else{for(p2=c.rhead[i];(p2->right)&&(p2->right->j<j);p2=p2->right);//空循环找到第一个列标大于或等于插入元素列标的元素v->right=p2->right;p2->right=v;}if(c.chead[j]==NULL||c.chead[j]->i>i)//插入元素所在列无非零元或首非零元的行标大于插入元素的行标{v->down=c.chead[j];c.chead[j]=v;}else{for(p2=c.chead[j];(p2->down)&&(p2->down->i<i);p2=p2->down);//空循环找到第一个行标大于或等于插入元素行标的元素v->down=p2->down;p2->down=v;}}}}}}void create(juzhen & M) //创建稀疏矩阵{int i,t=0;printf("输入矩阵行数和列数and非零元的个数,以空格隔开:\n");scanf("%d %d %d",&M.mu,&M.nu,&M.tu);printf("输入矩阵非零元的行,列,和数值(中间空格隔开):\n");for(i=1;i<=M.tu;i++)scanf("%d %d %d",&M.data[i].i,&M.data[i].j,&M.data[i].e); //输入三元组的元素for(i=1;i<=Size1;i++)//初始化rops【】M.rops[i]=0;for(i=1,t=1;i<=M.mu;i++)//得到各行第一个元素的序号{M.rops[i]=t;while(M.data[t].i<=i&&t<=M.tu)//遇到i行非零元,则t累加t++;}}void add(juzhen A,juzhen B,juzhen & C)//稀疏矩阵加法{int k=1,temp=0,k1=1, k2=1;//k1,k2,k分别控制A,B,C中非零元的序号变化printf("稀疏矩阵加法:\n");create(A);create(B);if(A.mu!=B.mu||A.nu!=B.nu)printf("格式不对,不能相加!\n");else{while(k1<=A.tu&&k2<=B.tu)//当A,B中的非零元都没用完{if(A.data[k1].i<B.data[k2].i)//A当前k1指向的元素的行标小于列标直接把data 【k1】的值赋给c中data【k】C.data[k++]=A.data[k1++];else if(A.data[k1].i>B.data[k2].i)//同上C.data[k++]=B.data[k2++];else//data[k1],data[k2]行标相同{if(A.data[k1].j>B.data[k2].j)//data[k1]列标大于data[k2]列标,则把data[k2]的值赋给data[k]C.data[k++]=B.data[k2++];else if(A.data[k1].j<B.data[k2].j)//同上C.data[k++]=A.data[k1++];else //行,列标都相同{temp=0;temp=A.data[k1].e+B.data[k2].e;if(temp)//相加后不为零{C.data[k].i=A.data[k1].i;C.data[k].j=A.data[k1].j;C.data[k].e=temp;k++;}k1++;k2++;}}}while(k1<=A.tu)//B中非零元已用完,A中还有非零元C.data[k++]=A.data[k1++];while(k2<=B.tu)//A中非零元已用完,B中还有非零元C.data[k++]=B.data[k2++];C.mu=A.mu;//确定C的行列数和非零元个数C.nu=A.nu;C.tu=k-1;}}void print(juzhen A)//输出稀疏矩阵{printf("\n矩阵为:\n");int i,j,k=1;if(A.mu==0)printf("矩阵为空!\n");else if(A.tu==0)//矩阵元素为空printf("零矩阵!\n");elsefor(i=1;i<=A.mu;i++)//逐行输出{for(j=1;j<=A.nu;j++){if(A.data[k].i==i&&A.data[k].j==j)//行和列分别对应相等则输出相应非零元,否则输出零printf("%5d",A.data[k++].e);elseprintf("%5d",0);}printf("\n");//该行输出结束,空行输出下一行}printf("\n");}void multy(juzhen A,juzhen B,juzhen &C)//稀疏矩阵乘法{int arow,brow,ccol,temp[51],p,q,t,tp,i;//各变量代表含义见下面printf("稀疏矩阵乘法:\n");create(A);create(B);if(A.nu!=B.mu)printf("格式错误,不能相乘!\n");else{C.mu=A.mu;//初始化c的行列及非零元个数C.nu=B.nu;C.tu=0;if(A.nu!=B.mu)printf("A,B格式不对不能相乘!\n");else //{for(arow=1;arow<=A.mu;arow++)//arow为当前A矩阵的行标{for(i=0;i<51;i++)//初始化temptemp[i]=0;if(arow<A.mu)tp=A.rops[arow+1];//tp为arow+1行的首非零元在data【】中的序号else //arow为最后一行tp=A.tu+1;for(p=A.rops[arow];p<tp;p++)//p为A中当前元素在data[]中的序号{brow=A.data[p].j;//brow为与B矩阵中的相应行对应的A中当前元素的列标if(brow<B.mu)t=B.rops[brow+1];//t为brow+1行的首非零元在B中data【】中的序号else //brow大小等于B.mut=B.tu+1;for(q=B.rops[brow];q<t;q++)//q为B中当前元素在B.data[]中的序号{ccol=B.data[q].j;//ccol:data[p]*data[q]所得结果所在的列temp[ccol]+=A.data[p].e*B.data[q].e;//temp【ccol】:相乘所得的C 矩阵中第arow行cool列元素的值}}for(ccol=1;ccol<=B.nu;ccol++)//if(temp[ccol])//temp【ccol】不为零,则把值赋到c中,c.tu加1。
基于mpi实现稀疏矩阵的乘法

基于MPI实现稀疏矩阵的乘法1. 引言稀疏矩阵是指大部分元素为零的矩阵,与之相对应的是稠密矩阵,其中大部分元素非零。
由于稀疏矩阵中有大量的零元素,传统的矩阵乘法算法在计算稀疏矩阵乘法时效率较低。
为了提高计算效率,我们可以利用并行计算的思想,使用MPI (Message Passing Interface)来实现稀疏矩阵的乘法。
MPI是一种用于编写并行程序的标准通信库,它定义了一组函数和语义,用于在多个进程之间进行通信和同步操作。
通过将任务划分为多个进程,每个进程负责处理一部分数据,并通过消息传递进行通信和协调,可以实现并行计算。
本文将介绍如何使用MPI实现稀疏矩阵的乘法算法。
首先我们会介绍稀疏矩阵的表示方法和存储格式,然后详细说明基于MPI的稀疏矩阵乘法算法的实现过程。
2. 稀疏矩阵的表示和存储格式稀疏矩阵有多种表示方法,常用的有三元组表示法、行压缩存储(CSR)和列压缩存储(CSC)。
三元组表示法将稀疏矩阵中非零元素的行、列和值分别存储在三个数组中。
这种表示方法简单直观,但对于大型稀疏矩阵来说,空间效率较低。
行压缩存储(CSR)是一种常用的稀疏矩阵存储格式。
在CSR格式中,我们将稀疏矩阵拆分为三个数组:值数组(values)、列指针数组(col_indices)和行偏移量数组(row_offsets)。
其中,值数组存储非零元素的值,列指针数组存储非零元素所在的列索引,行偏移量数组记录每一行第一个非零元素在值数组和列指针数组中的索引。
通过这种方式,我们可以快速访问稀疏矩阵中的非零元素。
列压缩存储(CSC)与CSR类似,只是将列指针数组变为行指针数组,将行偏移量数组变为列偏移量数组。
CSC格式适合于按列访问稀疏矩阵。
在本文中,我们将使用CSR格式来表示稀疏矩阵,并基于该格式实现稀疏矩阵的乘法算法。
3. 基于MPI的稀疏矩阵乘法算法基于MPI的稀疏矩阵乘法算法可以分为以下几个步骤:1.初始化MPI环境:在开始进行并行计算之前,需要初始化MPI环境,获取进程数量和进程编号等信息。
verilog实现稀疏矩阵乘法

verilog实现稀疏矩阵乘法
Verilog是一种硬件描述语言,用于描述数字电路。
稀疏矩阵
乘法是一种矩阵运算,其中一个或两个矩阵是稀疏矩阵,即大部分
元素为零。
在Verilog中实现稀疏矩阵乘法需要考虑以下几个方面:
1. 数据结构,首先,需要选择合适的数据结构来表示稀疏矩阵。
一种常见的方法是使用COO(坐标列表)、CSR(压缩稀疏行)或CSC(压缩稀疏列)等格式来存储稀疏矩阵的非零元素。
2. 矩阵乘法算法,实现稀疏矩阵乘法需要选择适合硬件实现的
算法。
常见的算法包括CSR格式的稀疏矩阵与稠密矩阵相乘、CSR
格式的稀疏矩阵与CSR格式的稀疏矩阵相乘等。
在Verilog中,需
要将所选的算法转化为硬件逻辑电路。
3. 控制逻辑,在Verilog中,需要实现控制逻辑来协调稀疏矩
阵乘法的各个步骤,包括读取稀疏矩阵的非零元素、执行乘法运算、累加结果等。
4. 存储器访问,稀疏矩阵乘法涉及大量的存储器访问操作,需
要合理设计存储器访问模块,以提高性能并减少资源占用。
总的来说,实现稀疏矩阵乘法的Verilog代码需要充分考虑稀疏矩阵的特点,并结合硬件逻辑的特点进行合理的设计和实现。
这需要深入理解稀疏矩阵乘法算法和Verilog语言的特性,以及对硬件电路设计有一定的了解。
希望这些信息对你有所帮助。
稀疏矩阵加法乘法

稀疏矩阵加法乘法稀疏矩阵是指其中大部分元素都是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中每个元素对应的行数和列数。
稀疏矩阵乘法

稀疏矩阵乘法给定两个 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]只会被计算⼀次,就是最终答案。
稀疏矩阵的加法和乘法

#include <stdio.h>#include <stdlib.h>#define MAX_SIZE 100typedef struct{int row;int col;int value;}square;square A[MAX_SIZE],B[MAX_SIZE];int m,n,coun_col[MAX_SIZE]={0};void print(square temp[MAX_SIZE]){int i,j,h=1;printf("矩阵如下:\n");for(i=0;i<temp[0].row;i++){for(j=0;j<temp[0].col;j++){if(i==temp[h].row && j==temp[h].col){printf("%4d",temp[h].value);h++;}elseprintf("%4d",0);}printf("\n");}}void sort(square temp[],int len){int i,j;square c;for(i=1;i<=len;i++)for(j=i+1;j<=len;j++){if(temp[i].row > temp[j].row){c = temp[i];temp[i] = temp[j];temp[j] = c;}}}void comp(square temp[],int len){int i;square C[MAX_SIZE];for(i=0;i<=len;i++){C[i].row = temp[i].col;C[i].col = temp[i].row;C[i].value = temp[i].value;}sort(C,len);printf("转置后");print(C);}void readdata_A(){int i;printf("请输入第一个矩阵的行数和列数:");scanf("%d%d",&A[0].row,&A[0].col);printf("输入第一个矩阵中非0元素的个数:");scanf("%d",&m);printf("按顺序输入矩阵行,列,值:\n");for(i=1;i<=m;i++){scanf("%d",&A[i].row);scanf("%d",&A[i].col);scanf("%d",&A[i].value);}print(A);comp(A,m);}void readdata_B(){int i;printf("请输入第二个矩阵的行数和列数:");scanf("%d%d",&B[0].row,&B[0].col);printf("输入第二个矩阵中非0元素的个数:");scanf("%d",&n);printf("按顺序输入矩阵行,列,值:\n");for(i=1;i<=n;i++){scanf("%d",&B[i].row);scanf("%d",&B[i].col);scanf("%d",&B[i].value);}print(B);comp(B,n);}int compare(int current_A,int current_B){if(A[current_A].row < B[current_B].row)return -1;else if(A[current_A].row > B[current_B].row)return 1;else{if(A[current_A].col < B[current_B].col)return -1;else if(A[current_A].col > B[current_B].col)return 1;elsereturn 0;}}void add(){int start_A=0,start_B=0,start_C=0,i;square C[MAX_SIZE];if(A[0].row != B[0].row || A[0].col != B[0].col){printf("所要相加的矩阵行数和列数不对应\n");exit(1);}printf("相加后");while(start_A <=m && start_B <=n){switch(compare(start_A,start_B)){case -1:C[start_C++] = A[start_A++];break;case 0:C[start_C] = B[start_B];C[start_C++].value = B[start_B++].value + A[start_A++].value;break;case 1:C[start_C++] = B[start_B++];break;default:printf("出错!!!\n");exit(1);}}for(i=start_A;i<=m;i++,start_C++){C[start_C] = A[i];}for(i=start_B;i<=n;i++,start_C++){C[start_C] = B[i];}print(C);}void cal_count(){int i;for(i=1;i<=n;i++){if(B[i].value!=0)coun_col[B[i].col]++;}}int exist(int row){int i;for(i=1;i<=m;i++){if(row == A[i].row)return 1;else if(row < A[i].row)return 0;}return 0;}void mul(){int row=0,count=1,j,i=1,sum=0,k,flag=0;if(A[0].col != B[0].row){printf("这两个矩阵无法相乘!!!\n");exit(1);}printf("相乘后");square C[MAX_SIZE];C[0].row = A[0].row;C[0].col = B[0].col;cal_count();while(row<=m){if(exist(row)){for(j=0;j<B[0].col;j++){if(coun_col[j]){for(i=1;i<=m;i++){if(A[i].row == row){for(k=1;k<=n;k++){if(B[k].col == j && A[i].col == B[k].row){flag=1;sum+=A[i].value*B[k].value;}}}//end ifif(A[i].row>row)break;}//end for}//end ifif(flag){C[count].row=row;C[count].col=j;C[count].value=sum;sum=0;count++;flag = 0;}}//end for}//end ifrow++;}//end whileprint(C);}int main(){readdata_A();readdata_B();add();mul();return 0;}。
拓展阅读3——稀疏矩阵的相乘

稀疏矩阵的相乘*两个矩阵相乘的经典算法是大家所熟悉的,设Q=M×N其中,M 是m 1×n 1矩阵,N 是m 2×n 2矩阵。
当n 1=m 2时有:for (i=1;i<=m1;++i )for(j=1;j<=n2;++j){Q[i][j]=0;for(k=1;k<=n1;++k)Q[i][j]+=M[i][k]×N[k][j];}此算法的时间复杂度是O(m 1×n 1×n 2)。
当矩阵变成稀疏矩阵,并且用三元组表作存储结构时,上面这个算法就不能用了,下面我们讨论稀疏矩阵三元组表的相乘算法。
已知稀疏矩阵A(m 1× n 1)和B(m 2× n 2),求乘积C(m 1× n 2)。
稀疏矩阵A 、B 、C 及它们对应的三元组表A.data 、B.data 、C.data 如图1所示。
A=⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡000203008005 B=⎥⎥⎥⎥⎦⎤⎢⎢⎢⎢⎣⎡-01500720 C=⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡-40150108 115148233312ij v 114523712221-v j i 42315221021811-v j i 图1 稀疏矩阵相乘图例由矩阵乘法规则知:C (i ,j )=A(i,1)×B(1,j)+A(i,2)×B(2,j)+…+A(i,n)×B(n,j)=)11(),(),(2,11n j m i j k B k i A n k ≤≤≤≤⨯∑=矩阵用二维数组表示时,在经典算法中,不论A(i,k)与B(k,j)的值是否为零,都要进行一次乘法运算,而在三元组表示的稀疏矩阵相乘时,只需从A.data 和B.data 中找到A.data 中列值与B.data 中行值相等的各对元素相乘并将结果累加即可。
为此需要在B.data 中找到矩阵B 第k 行中所有非零元素,跟矩阵转置改进算法相同的原理,我们引入num 和rpot 两个向量。
基于mapreduce的稀疏矩阵乘法算法

基于mapreduce的稀疏矩阵乘法算法组长:吴建堃组员:白野朵宝宝目录一、课题研究目的二、稀疏矩阵介绍(一)稀疏矩阵乘法介绍(三元组) (2)(二) Mapreduce介绍 (4)(三)实验环境配置 (7)(四)创建代码(来自网络的代码) (10)(五)组员总结 (16)一、课题研究目的。
矩阵乘法运算是一种基本运算。
而扩大矩阵乘法的运算规模并降低其运算时间,将有利于满足机器学习算法处理大规模数据的要求。
将MapReduce并行框架用于分块矩阵乘法,实现一种用于大规模矩阵乘法运算的方法。
理论分析和实验结果表明该方法在处理大规模矩阵乘法上具有极大的潜能,并且随着计算节点的增加从而获得较好的加速比。
二、稀疏矩阵介绍。
人们无法给出稀疏矩阵的确切定义,一般都只是凭个人的直觉来理解这个概念,即矩阵中非零元素的个数远远小于矩阵元素的总数,并且非零元素没有分布规律。
对于那些零元素数目远远多于非零元素数目,并且非零元素的分布没有规律的矩阵称为稀疏矩阵(六)稀疏矩阵乘法介绍(三元组)当矩阵M、N是稀疏矩阵时,我们可以采用三元组表的表示形式来实现矩阵的乘。
采用三元组表的方法来实现时,因为三元组只对矩阵的非零元素做存储所以可以采用固定三元组表a中的元素(i,k,Mik)(1≤i≤m1,1≤k≤n1),在三元组表b中找所有行号为k的的对应元素(k,j, Nkj)(1≤k≤m2,1≤j≤n2)进行相乘、累加,从而得到Q[i][j],即以三元组表a中的元素为基准,依次求出其与三元组表b的有效乘积。
算法中附设两个向量num[]、first[],其中num[row]表示三元组表b中第row 行非零元素个数(1≤row≤m2), first[row]表示三元组表b中第row行第一个非零元素所在的位置。
显然,first[row+1]-1指向三元组表b中第row行最后一个非零元素的位置。
first[1]=1;first[row]=first[row-1]+num[row-1], 2≤row≤m2+1。
用三元组表示稀疏矩阵的乘法

该结点除了( row , col , value )以外,还要有以下两个链域:
right: down: 用于链接同一列中的下一个非零元素。
row Down
col
Value right
第十二讲
1 1 3
1 4 5
2 2 -1
3 1 3
图5.23 十字链表的结构
第十二讲
十字链表的结构类型说明如下:
typedef struct OLNode
第十二讲
用三元组表实现稀疏矩阵的乘法运算
第十二讲
两个矩阵相乘也是矩阵的一种常用的运算。设矩阵 M 是
m1×n1 矩阵, N 是 m2×n2 矩阵;若可以相乘,则必须满足矩
阵 M 的列数 n1 与矩阵 N 的行数 m2 相等,才能得到结果矩阵 Q=M×N(一个m1×n2的矩阵)。
数学中矩阵Q中的元素的计算方法如下:
矩阵不仅节约了空间,而且使得矩阵某些运算的运算时间比经
典算法还少。但是在进行矩阵加法、减法和乘法等运算时,有 时矩阵中的非零元素的位置和个数会发生很大的变化。如
A=A+B, 将矩阵B加到矩阵A上,此时若还用三元组表表示法,
势必会为了保持三元组表“以行序为主序”而大量移动元素。
第十二讲
在十字链表中,矩阵的每一个非零元素用一个结点表示,
0 1 N 2 0
2 0 4 0
0 Q 1 0
6 0 4
图5.17 Q=M×N
第十二讲
图5.18 矩阵M、N、Q的三元组表
第十二讲
经典算法中,不论 M [ i ][ k ]、 N [ k ][ j ]是否为零,
for(k=1; k<=n1; k++)
实验指导书--稀疏矩阵存储与向量乘运算

上机实验一: 稀疏矩阵存储与向量乘运算一、实验目的:学习稀疏矩阵存储的Compressed Row Storage 技术与此基础上的矩阵向量乘方法,分析其(内存)空间与时间复杂度与直接存储方法之间的差别。
二、基本知识:通过有限元方法离散的得到的矩阵都是稀疏矩阵,即其大部分矩阵元素都为0。
因此在程序编写过程中采用二维的数组来存储非常浪费内存,因此需要采用一种有效的方法来保存稀疏矩阵。
Compressed Row Storage(CRS)就是这样一种常用高效的稀疏存储技术。
考虑一个一般的N×N矩阵MatA, 如果以二维数组存储,其内存需求为:O(N2)矩阵向量乘运算量为:O(N2).对于一个稀疏N×N矩阵MatA,其非零元素个数为Ns, 定义三个一维数组:-Val[Ns]按行-列方式依次存储矩阵中每个非零元素;-Col_ind[Ns] 对应记录Val 中每个元素所在的列数;-row_ptr[N+1] 记录每一行第一个元素在Val中的位置。
如此:•第i 行非零元素的个数为:row_ptr[i+1] - row_ptr[ i ]•第i 行的非零元素有:val[row_ptr[ i ]], ... , val[ row_ptr[ i+1 ] -1 ]。
【例】:0 1 2 3 4 512345C++ Code Demo//Compressed Row Storage format//for a sparse square (mSize X mSize) matrixpublic class CRS{//the values of the nonzero elements of the matrixfloat[] val;//the column indices of the elements in val arrayint[] col_idx;//locations in the val and col_idx array that start a rowint[] row_ptr;//the size of the matrix: the number of rowsint mSize=0;//constructor that takes a sparse matrix and convert it to a CRS object CRS( float[][] matrix){...}//print the matrix in CRS format.public void printCRS(){...}//test the programpublic static void main(String[] args){...}}CRS( float[][] matrix){int i, j, index;//the total number of nonzero in the matrixint totalNonZeros;//get the number of rows and columnsmSize = matrix.length;//get the total number of nonzero entries in the matrixtotalNonZeros = 0;for( i=0; i<mSize; i++){for( j=0; j<mSize; j++){if(matrix[i][j] != 0)totalNonZeros++;}}//allocate memory for val and col_idx arrayval = new float[ totalNonZeros ];col_idx = new int[ totalNonZeros ];//allocate memory for row_ptrrow_ptr = new int[ mSize+1];row_ptr[ 0 ] = 0;//store the matrix in CRS formatindex = 0;// point to the next position to store the valuefor( i=0; i<mSize; i++ ){//each rowfor( j=0; j<mSize; j++ ){//each columnif( matrix[i][j] != 0 ){//add the value to valval[ index ] = matrix[ i ][ j ];//record the column index in col_idxcol_idx[ index ] = j;index++;}}//update row_ptrrow_ptr[ i+1 ] = index;}}//end of CRS( float[][] matrix)//test the programpublic static void main(String[] args){float[][] matrix = {{10, 0, 0, 0, -2, 0},{3, 9, 0, 0, 0, 3},{0, 7, 8, 7, 0, 0},{3, 0, 8, 7, 5, 0},{0, 8, 0, 9, 9, 13},{0, 4, 0, 0, 2, -1}};System.out.println("the original sparse matrix");for(int i=0; i<6; i++){for(int j=0; j<6; j++){System.out.print(matrix[i][j]+", ");}System.out.println();}System.out.println();CRS crs = new CRS(matrix);crs.printMatrix();crs.printCRS();}三、实验任务(课上检验,不要求实验报告):实验一: 用Matlab实现一个10×10稀疏矩阵的CRS存储步骤一:生成一个随机的二维矩阵。
基于mpi实现稀疏矩阵的乘法

基于mpi实现稀疏矩阵的乘法要基于MPI实现稀疏矩阵的乘法,首先需要将稀疏矩阵存储在内存中的数据结构转换成适合在MPI上进行并行计算的数据结构。
稀疏矩阵通常采用压缩稀疏行(Compressed Sparse Row,CSR)格式进行存储。
在CSR格式中,矩阵被分为三个数组:val、col_ind和row_ptr。
val数组存储所有非零元素的值,col_ind数组存储对应非零元素的列索引,而row_ptr数组存储每一行的起始位置在val和col_ind数组中的索引。
在基于MPI的并行计算中,每个MPI进程将会处理部分矩阵的行。
因此,需要将稀疏矩阵按照行进行划分,并将行划分的结果分配给每个MPI进程。
下面是一个基于MPI的稀疏矩阵乘法的伪代码:```#include <mpi.h>MPI_Init(NULL, NULL);int rank, size;MPI_Comm_rank(MPI_COMM_WORLD, &rank);MPI_Comm_size(MPI_COMM_WORLD, &size);// 假设稀疏矩阵A和向量x的CSR格式为val、col_ind和row_ptr// 假设矩阵A的行数为M,列数为N,向量x的长度为N double* val_A;int* col_ind_A;int* row_ptr_A;int M, N;// 由主进程读取稀疏矩阵A和向量x,并分发给其他进程if (rank == 0) {// 从文件或其他地方读取稀疏矩阵A和向量x的值,并存储在val_A、col_ind_A和row_ptr_A等变量中// 设置矩阵A的行数M和列数N// 将稀疏矩阵A和向量x的数据按行划分,并发送给其他进程for (int i = 1; i < size; i++) {// 计算每个MPI进程处理的行数和起始行索引int rows = ...; // 每个进程处理的行数int start_row = ...; // 每个进程处理的起始行索引// 发送稀疏矩阵A的值、列索引和行指针数组给其他进程 // 发送向量x的值给其他进程MPI_Send(val_A + start_row, rows * N, MPI_DOUBLE, i, 0, MPI_COMM_WORLD);MPI_Send(col_ind_A + start_row, rows * N, MPI_INT, i, 0, MPI_COMM_WORLD);MPI_Send(row_ptr_A + start_row, rows + 1, MPI_INT, i, 0, MPI_COMM_WORLD);MPI_Send(x, N, MPI_DOUBLE, i, 0,MPI_COMM_WORLD);}} else {// 接收稀疏矩阵A和向量x的数据MPI_Recv(val_A, <每个进程处理的行数> * N,MPI_DOUBLE, 0, 0, MPI_COMM_WORLD,MPI_STATUS_IGNORE);MPI_Recv(col_ind_A, <每个进程处理的行数> * N, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);MPI_Recv(row_ptr_A, <每个进程处理的行数> + 1, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);MPI_Recv(x, N, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);}// 在每个进程上计算稀疏矩阵乘法的结果// 假设结果向量y的长度为Mdouble* y = new double[<每个进程处理的行数>];for (int i = 0; i < <每个进程处理的行数>; i++) {double sum = 0.0;for (int j = row_ptr_A[i]; j < row_ptr_A[i + 1]; j++) {sum += val_A[j] * x[col_ind_A[j]];}y[i] = sum;}// 将每个进程上的计算结果发送给主进程if (rank == 0) {// 接收其他进程的计算结果for (int i = 1; i < size; i++) {double* recv_buf = new double[<每个进程处理的行数>]; MPI_Recv(recv_buf, <每个进程处理的行数>,MPI_DOUBLE, i, 0, MPI_COMM_WORLD,MPI_STATUS_IGNORE);// 将每个进程的计算结果合并到结果向量y中for (int j = 0; j < <每个进程处理的行数>; j++) {y[<每个进程的处理起始行索引> + j] = recv_buf[j];}delete[] recv_buf;}} else {// 发送计算结果给主进程MPI_Send(y, <每个进程处理的行数>, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD);}// 主进程输出结果向量yif (rank == 0) {for (int i = 0; i < M; i++) {std::cout << y[i] << " ";}std::cout << std::endl;}// 释放内存delete[] val_A;delete[] col_ind_A;delete[] row_ptr_A;delete[] x;delete[] y;MPI_Finalize();```请注意,上述代码中的一些变量和计算的具体实现可能需要根据你的具体需求进行调整。
稀疏矩阵的存储和乘法操作

稀疏矩阵的存储和乘法操作⼀稀疏矩阵的存储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.⼗字链表当稀疏矩阵的⾮零元个数和位置在操作过程中变化较⼤时,就不易采⽤顺序存储结构来表⽰三元组的线性表。
数据结构三元组稀疏矩阵乘法代码

数据结构三元组稀疏矩阵乘法代码代码:```pythonclass SparseMatrix:def __init__(self, rows, columns):self.rows = rowsself.columns = columnsself.elements = []def insert(self, row, column, value):if row >= 0 and row < self.rows and column >= 0 and column < self.columns:self.elements.append((row, column, value))else:raise IndexError("Invalid index")def multiply(self, other):if self.columns != other.rows:raise ValueError("Invalid matrix dimensions")result_matrix = SparseMatrix(self.rows, other.columns)for i in range(self.rows):for j in range(other.columns):result = 0for k in range(len(self.elements)):if self.elements[k][0] == i:for l in range(len(other.elements)):if other.elements[l][1] == j:if self.elements[k][1] == other.elements[l][0]:result += self.elements[k][2] * other.elements[l][2] if result != 0:result_matrix.insert(i, j, result)return result_matrix# 创建稀疏矩阵1sparse_matrix1 = SparseMatrix(3, 3)sparse_matrix1.insert(0, 0, 1)sparse_matrix1.insert(0, 2, 2)sparse_matrix1.insert(1, 1, 3)sparse_matrix1.insert(2, 0, 4)# 创建稀疏矩阵2sparse_matrix2 = SparseMatrix(3, 3)sparse_matrix2.insert(0, 1, 5)sparse_matrix2.insert(1, 0, 6)sparse_matrix2.insert(1, 2, 7)sparse_matrix2.insert(2, 2, 8)# 稀疏矩阵乘法result = sparse_matrix1.multiply(sparse_matrix2)# 输出结果for i in range(result.rows):for j in range(result.columns):print(result.elements[i * result.columns + j][2], end=" ")print()```该代码实现了三元组表示的稀疏矩阵的乘法运算。
稀疏矩阵相乘

right 存放行链表指针。
整个稀疏矩阵定义为类 Matrix 的一个对象,*headnode 给出整个附加头结点链表的附
加头结点的地址。
headHale Waihona Puke downnext right
head down
row value
col rig非ht零元素结点
附加头结点
2.2 主要算法
非零元素结点
基于三元组及十字链表的稀疏矩阵乘法 Matrix Matrix::Mul( Matrix b) //矩阵乘法的实现
.
稀疏矩阵相乘
1 问题描述
1.1 稀疏矩阵的三元组及十字链表表示
(1)稀疏矩阵及其三元组表示 稀疏矩阵
0 0 0 22 0 0 15
0 11 0 0 0 17 0
0
0
0 6 0 0
0
0 0 0 0 0 39 0
91 0
0 0
0 28
0 0
0 0
0 0
0 0
行(row) 列(col) 值(value)
{
if(this->Col==b.Row)
{ Matrix C(this->Row,b.Col); //以 A 矩阵的行和 b 矩阵的列为行列建立稀疏矩阵
float value; node *Row_head,*Col_head; //设两个指针,一个充当行头指针,一个为列指针 for(int i=1;i<=temp;i++) //先确定行,再求出 C 矩阵在该行各列的元素
[0]
0
3
22
[1]
0
6
15
[2]
1
1
11
用十字链表和一般方法分别实现稀疏矩阵的乘法和加法资料

#include<stdio.h>#include<malloc.h>#define Size 2501# define Size1 51typedef struct{int i;int j;int e;//非零元的值}triple; //定义三元组typedef struct{triple data[Size+1];//矩阵中的元素int rops[Size1+1];// rops[i]为第i行元素中的首非零元在data[]中的序号int mu;//行数int nu;//列数int tu;//非零元数} juzhen;//定义矩阵typedef struct node// 定义十字链表元素{int i,j,e;struct node *right,*down;// 该非零元所在行表和列表的后继元素}node,*link;typedef struct // 定义十字链表对象结构体{link *rhead,*chead;//行和列的头指针int m,n,t;// 系数矩阵的行数,列数,和非零元素个数}crosslist;void createcross(crosslist &M)//建立十字链表{int i,j,e,k;node *p,*q;printf("输入行,列和非零元数,空格隔开:\n");scanf("%d %d %d",&M.m,&M.n,&M.t);M.rhead=(link *)malloc((M.m+1)*sizeof(link));//给行和列的头指针分配内存M.chead=(link *)malloc((M.n+1)*sizeof(link));for(k=1;k<=M.m;k++)//初始化行,列的头指针M.rhead[k]=NULL;for(k=1;k<=M.n;k++)M.chead[k]=NULL;printf("输入非零元的行,列和值,空格隔开:\n");for(k=1;k<=M.t;k++)//输入非零元{scanf("%d %d %d",&i,&j,&e);p=(node *)malloc(sizeof(node));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{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->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;}}}void printcross(crosslist A)//输出十字链表{if(A.m==0)printf("十字链表为空!\n");else{printf("十字链表为:\n");int i,j;for(i=1;i<=A.m;i++){link p=A.rhead[i];for(j=1;j<=A.n;j++){if((p)&&(j==p->j)){printf("%5d",p->e);p=p->right; }elseprintf("%5d",0);}printf("\n");}}printf("\n");}crosslist addcross(){printf("十字链表加法:\n");crosslist a,b;// 创建两个十字链表对象,并初始化createcross(a);createcross(b);node *pre,*h[51],*pa,*pb,*q;//定义辅助指针,pa,pb分别为a,b当前比较的元素,pre为pa的前驱元素int i,j,k=0,m,n; //h[j]指向j列的当前插入位置if(a.m!=b.m||a.n!=b.n)printf("格式不对,不能相加!\n");else{for(i=1;i<=a.m;i++){pa=a.rhead[i];pb=b.rhead[i];pre=NULL;for(j=1;j<=a.n;j++)h[j]=NULL;while(pb){p=(node *)malloc(sizeof(node)); // 开辟新节点,存储b中取出的元素p->i=pb->i;p->j=pb->j;p->e=pb->e;if(pa==NULL||pa->j>pb->j)//当a此行已经检查完或者pb因该放在pa前面{if (pre==NULL)a. rhead[p->i]=p;elsepre->right=p;p->right=pa;pre=p;if (h[p->j]==NULL)//当前插入位置下面无非零元//因为是逐行处理,so,h[p->j],依次下移//因此每次都是指向插入的位置{a. chead [p->j]= p;p->down = NULL;}else{p->down = h[p->j]->down;h[p->j]->down = p;}h[p->j]=p;//*******h[p->j]下移指向下次插入的位置pb=pb->right;//pb指向该行下个元素}else if((pa&&pa->j<pb->j))//只要移动pa的指针****先不加||(pb==NULL&&pa){pre = pa;h[pa->j]=pa;//移动h[],使其指向下次插入的位置pa = pa->right;}else if(pa->j==pb->j){pa->e+=pb->e;if(pa->e)//不为零{pre=pa;h[pa->j]=pa;pb=pb->right;//加else//pa->e为零,删除节点{if (pre ==NULL)a.rhead [pa->i]=pa->right;else{pre->right=pa->right;}p=pa;//p指向pa,用来在下面修改列指针pa=pa->right;if (h [p->j]==NULL)a.chead [p->j]=p->down;else{h[p->j]->down=p->down;}free(p);pb=pb->right;}}}}}return a;}void multycross(crosslist &c)//十字链表乘法{node *p,*q,*u,*v,*p1,*p2;crosslist a,b;link *r;int i,j,k,e;printf("十字链表乘法:\n");createcross(a);createcross(b);if(a.n!=b.m)printf("格式错误,不能相乘!\n");else{c.m=a.m;c.n=b.n;c.t=0;c.rhead=(link *)malloc((a.m+1)*sizeof(link));//给行和列的头指针分配内存c.chead=(link *)malloc((b.n+1)*sizeof(link));for(k=1;k<=a.m;k++)//初始化行,列的头指针c.rhead[k]=NULL;for(k=1;k<=b.n;k++)c.chead[k]=NULL;r=(link *)malloc((b.n+1)*sizeof(link));for(i=1;i<=a.m;i++){u=(node *)malloc(sizeof(node));u->e=0;u->i=0;u->j=0;for(k=1;k<=b.n;k++)//初始化r[]r[k]=u;p1=p=a.rhead[i];for(j=1;j<=b.n;j++){p=p1;q=b.chead[j];v=(node *)malloc(sizeof(node));//初始化v,v为将插入c矩阵的元素v->e=0;v->i=i;v->j=j;while(p&&q){if(p->j>q->i)q=q->down;else if(p->j<q->i)p=p->right;else{v->e+=p->e*q->e;p=p->right;q=q->down;}}if(v->e)//如果不为零,则插入c矩阵中{//同建立十字链表if(c.rhead[i]==NULL||c.rhead[i]->j>j)//插入元素所在行无非零元或首非零元的列标大于插入元素的列标{v->right=c.rhead[i];c.rhead[i]=v;}else{for(p2=c.rhead[i];(p2->right)&&(p2->right->j<j);p2=p2->right);//空循环找到第一个列标大于或等于插入元素列标的元素v->right=p2->right;p2->right=v;}if(c.chead[j]==NULL||c.chead[j]->i>i)//插入元素所在列无非零元或首非零元的行标大于插入元素的行标{v->down=c.chead[j];c.chead[j]=v;}else{for(p2=c.chead[j];(p2->down)&&(p2->down->i<i);p2=p2->down);//空循环找到第一个行标大于或等于插入元素行标的元素v->down=p2->down;p2->down=v;}}}}}}void create(juzhen & M) //创建稀疏矩阵{int i,t=0;printf("输入矩阵行数和列数and非零元的个数,以空格隔开:\n");scanf("%d %d %d",&M.mu,&M.nu,&M.tu);printf("输入矩阵非零元的行,列,和数值(中间空格隔开):\n");for(i=1;i<=M.tu;i++)scanf("%d %d %d",&M.data[i].i,&M.data[i].j,&M.data[i].e); //输入三元组的元素for(i=1;i<=Size1;i++)//初始化rops【】M.rops[i]=0;for(i=1,t=1;i<=M.mu;i++)//得到各行第一个元素的序号{M.rops[i]=t;while(M.data[t].i<=i&&t<=M.tu)//遇到i行非零元,则t累加t++;}}void add(juzhen A,juzhen B,juzhen & C)//稀疏矩阵加法{int k=1,temp=0,k1=1, k2=1;//k1,k2,k分别控制A,B,C中非零元的序号变化printf("稀疏矩阵加法:\n");create(A);create(B);if(A.mu!=B.mu||A.nu!=B.nu)printf("格式不对,不能相加!\n");else{while(k1<=A.tu&&k2<=B.tu)//当A,B中的非零元都没用完{if(A.data[k1].i<B.data[k2].i)//A当前k1指向的元素的行标小于列标直接把data 【k1】的值赋给c中data【k】C.data[k++]=A.data[k1++];else if(A.data[k1].i>B.data[k2].i)//同上C.data[k++]=B.data[k2++];else//data[k1],data[k2]行标相同{if(A.data[k1].j>B.data[k2].j)//data[k1]列标大于data[k2]列标,则把data[k2]的值赋给data[k]C.data[k++]=B.data[k2++];else if(A.data[k1].j<B.data[k2].j)//同上C.data[k++]=A.data[k1++];else //行,列标都相同{temp=0;temp=A.data[k1].e+B.data[k2].e;if(temp)//相加后不为零{C.data[k].i=A.data[k1].i;C.data[k].j=A.data[k1].j;C.data[k].e=temp;k++;}k1++;k2++;}}}while(k1<=A.tu)//B中非零元已用完,A中还有非零元C.data[k++]=A.data[k1++];while(k2<=B.tu)//A中非零元已用完,B中还有非零元C.data[k++]=B.data[k2++];C.mu=A.mu;//确定C的行列数和非零元个数C.nu=A.nu;C.tu=k-1;}}void print(juzhen A)//输出稀疏矩阵{printf("\n矩阵为:\n");int i,j,k=1;if(A.mu==0)printf("矩阵为空!\n");else if(A.tu==0)//矩阵元素为空printf("零矩阵!\n");elsefor(i=1;i<=A.mu;i++)//逐行输出{for(j=1;j<=A.nu;j++){if(A.data[k].i==i&&A.data[k].j==j)//行和列分别对应相等则输出相应非零元,否则输出零printf("%5d",A.data[k++].e);elseprintf("%5d",0);}printf("\n");//该行输出结束,空行输出下一行}printf("\n");}void multy(juzhen A,juzhen B,juzhen &C)//稀疏矩阵乘法{int arow,brow,ccol,temp[51],p,q,t,tp,i;//各变量代表含义见下面printf("稀疏矩阵乘法:\n");create(A);create(B);if(A.nu!=B.mu)printf("格式错误,不能相乘!\n");else{C.mu=A.mu;//初始化c的行列及非零元个数C.nu=B.nu;C.tu=0;if(A.nu!=B.mu)printf("A,B格式不对不能相乘!\n");else //{for(arow=1;arow<=A.mu;arow++)//arow为当前A矩阵的行标{for(i=0;i<51;i++)//初始化temptemp[i]=0;if(arow<A.mu)tp=A.rops[arow+1];//tp为arow+1行的首非零元在data【】中的序号else //arow为最后一行tp=A.tu+1;for(p=A.rops[arow];p<tp;p++)//p为A中当前元素在data[]中的序号{brow=A.data[p].j;//brow为与B矩阵中的相应行对应的A中当前元素的列标if(brow<B.mu)t=B.rops[brow+1];//t为brow+1行的首非零元在B中data【】中的序号else //brow大小等于B.mut=B.tu+1;for(q=B.rops[brow];q<t;q++)//q为B中当前元素在B.data[]中的序号{ccol=B.data[q].j;//ccol:data[p]*data[q]所得结果所在的列temp[ccol]+=A.data[p].e*B.data[q].e;//temp【ccol】:相乘所得的C 矩阵中第arow行cool列元素的值}}for(ccol=1;ccol<=B.nu;ccol++)//if(temp[ccol])//temp【ccol】不为零,则把值赋到c中,c.tu加1。
稀疏矩阵乘法算法

稀疏矩阵乘法算法
稀疏矩阵乘法算法是一种针对稀疏矩阵进行乘法运算的优化算法。
在稀疏矩阵中,大部分元素都为0,只有少数元素具有非零值。
传统的矩阵乘法算法在处理稀疏矩阵时会浪费大量的时间和空间资源,因此需要采用更加高效的算法。
稀疏矩阵乘法算法主要有两种实现方式:行压缩存储和列压缩存储。
行压缩存储是将矩阵的每一行转换为一个一维数组,并记录每一行中非零元素的列号和值。
列压缩存储则是将矩阵的每一列转换为一个一维数组,并记录每一列中非零元素的行号和值。
这两种存储方式能够有效地减少矩阵存储所需要的空间。
在进行稀疏矩阵乘法运算时,可以通过对矩阵进行预处理,将非零元素的行列组合成一个三元组,并按照行序或列序进行排序。
这样可以大大降低运算复杂度。
具体实现过程中,可以采用分块法、分治法和并行计算等技术,进一步提高算法的效率。
稀疏矩阵乘法算法在大规模稀疏矩阵运算中具有重要的应用,如图像处理、信号处理、网络优化等。
因此,对于稀疏矩阵乘法算法的研究和优化,具有重要的理论和实际价值。
- 1 -。
pytorch 稀疏矩阵乘法

pytorch 稀疏矩阵乘法PyTorch 是已经成为了深度学习领域中最具有代表性的一种框架,而其本身的灵活性和强大性质也为其赢得了大量的忠实用户,其中之一就是在矩阵计算方面进行优化的 PyTorch 稀疏矩阵乘法。
对于机器学习和深度学习任务特别有效,不仅能提高执行效率,同时还可以大大减少计算和存储开销。
本篇文章主要介绍 PyTorch 稀疏矩阵乘法的应用和实现细节。
## 什么是稀疏矩阵稀疏矩阵是指大多数元素为零的矩阵。
在矩阵计算中,大多数操作都会涉及到元素的乘法操作,而稀疏矩阵的计算往往能够通过改进算法,提高计算效率。
在深度学习中,我们通常会处理高维矩阵,很多时候,这些高维矩阵的大多数元素都为零,这时候就可以利用稀疏矩阵优化计算,加快模型的训练速度。
## 稀疏矩阵乘法稀疏矩阵乘法是指对两个稀疏矩阵进行乘法操作的过程。
可以用矩阵的标准乘法表达式进行定义,如下所示:$$ c_{i,j}=\sum_k a_{i,k}b_{k,j} $$其中,矩阵 $A$ 的维度为 $m \times n$,矩阵$B$ 的维度为 $n \times k$,矩阵 $C$ 的维度为 $m\times k$。
对于稀疏矩阵乘法,相应的优化算法能够通过改变乘法操作的顺序来避免大量的费时操作,并实现更高效的计算。
下面介绍 PyTorch 中的稀疏矩阵乘法实现方法。
## PyTorch 稀疏矩阵乘法的实现PyTorch 中使用稀疏矩阵进行计算的方法是,将稀疏矩阵的非零元素保存在稀疏张量(sparse tensor)的indices、values 和 size 属性中,并通过 PyTorch 提供的稀疏矩阵乘法函数进行计算。
### 创建稀疏张量PyTorch 中提供了两种方式创建稀疏张量。
第一种方式是先创建一个密集矩阵,再将其转换为稀疏矩阵。
第二种方式是直接创建稀疏张量。
#### 创建密集矩阵下面是如何使用 PyTorch 创建密集矩阵的示例代码:```python import torchdense_matrix = torch.randn(3, 5) ```#### 将密集矩阵转换为稀疏矩阵下面是如何使用 PyTorch 将密集矩阵转换为稀疏矩阵的示例代码:```python sparse_matrix =torch.sparse_coo_tensor( dense_matrix.nonzero(), dense_matrix[dense_matrix.nonzero()],size=dense_matrix.shape ) ```在上述代码中,我们首先使用dense_matrix.nonzero() 获取矩阵 non-zero 元素的索引,然后使用 dense_matrix[dense_matrix.nonzero()]获取该索引处元素的值,最后使用这些索引和值创建稀疏矩阵。
c语言稀疏矩阵应用代码实现三元组,十字链表下的稀疏矩阵的加、转、乘的实现。

c语言稀疏矩阵应用代码实现三元组,十字链表下的稀疏矩阵的加、转、乘的实现。
在C语言中,实现稀疏矩阵的加法、转置和乘法涉及复杂的数据结构和算法。
其中,常用的表示稀疏矩阵的两种数据结构是三元组和十字链表。
下面我将为您提供一个简单的示例代码,用C语言实现稀疏矩阵的加法、转置和乘法操作,使用三元组表示法来表示稀疏矩阵。
首先,我们需要定义表示稀疏矩阵的三元组结构体:```c#include<stdio.h>#define MAX_SIZE100typedef struct{int row;int col;int value;}Element;typedef struct{int rows;int cols;int num_elements;Element data[MAX_SIZE];}SparseMatrix;```接下来,我们实现稀疏矩阵的加法、转置和乘法函数:```c#include<stdbool.h>//加法函数SparseMatrix addSparseMatrix(SparseMatrix matrix1,SparseMatrix matrix2){ SparseMatrix result;result.rows=matrix1.rows;result.cols=matrix1.cols;result.num_elements=0;int i=0,j=0;while(i<matrix1.num_elements&&j<matrix2.num_elements){if(matrix1.data[i].row<matrix2.data[j].row||(matrix1.data[i].row==matrix2.data[j].row&&matrix1.data[i].col<matrix2.data[j].col)){ result.data[result.num_elements++]=matrix1.data[i++];}else if(matrix1.data[i].row>matrix2.data[j].row||(matrix1.data[i].row==matrix2.data[j].row&&matrix1.data[i].col>matrix2.data[j].col)){ result.data[result.num_elements++]=matrix2.data[j++];}else{Element element;element.row=matrix1.data[i].row;element.col=matrix1.data[i].col;element.value=matrix1.data[i].value+matrix2.data[j].value;if(element.value!=0){result.data[result.num_elements++]=element;}i++;j++;}}while(i<matrix1.num_elements){result.data[result.num_elements++]=matrix1.data[i++];}while(j<matrix2.num_elements){result.data[result.num_elements++]=matrix2.data[j++];}return result;}//转置函数SparseMatrix transposeSparseMatrix(SparseMatrix matrix){ SparseMatrix result;result.rows=matrix.cols;result.cols=matrix.rows;result.num_elements=matrix.num_elements;int count[matrix.cols];int index[matrix.cols];for(int i=0;i<matrix.cols;i++){count[i]=0;}for(int i=0;i<matrix.num_elements;i++){count[matrix.data[i].col]++;}index[0]=0;for(int i=1;i<matrix.cols;i++){index[i]=index[i-1]+count[i-1];}for(int i=0;i<matrix.num_elements;i++){int j=index[matrix.data[i].col];result.data[j].row=matrix.data[i].col;result.data[j].col=matrix.data[i].row;result.data[j].value=matrix.data[i].value;index[matrix.data[i].col]++;}return result;}//乘法函数SparseMatrix multiplySparseMatrix(SparseMatrix matrix1,SparseMatrix matrix2){ SparseMatrix result;if(matrix1.cols!=matrix2.rows){result.rows=0;result.cols=0;result.num_elements=0;return result;}result.rows=matrix1.rows;result.cols=matrix2.cols;result.num_elements=0;bool visited[matrix2.cols];for(int i=0;i<matrix2.cols;i++){visited[i]=false;}for(int i=0;i<matrix1.num_elements;i++){for(int j=0;j<matrix2.num_elements;j++){if(matrix1.data[i].col==matrix2.data[j].row){Element element;element.row=matrix1.data[i].row;element.col=matrix2.data[j].col;element.value=matrix1.data[i].value*matrix2.data[j].value; result.data[result.num_elements++]=element;visited[matrix2.data[j].col]=true;}}}for(int i=0;i<matrix2.cols;i++){if(!visited[i]){for(int j=0;j<matrix1.rows;j++){Element element;element.row=j;element.col=i;element.value=0;result.data[result.num_elements++]=element;}}}return result;}```请注意,上述代码只是一个简单示例,实际应用中可能需要根据具体需求进行优化和扩展。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
稀疏矩阵的乘法实现程序:1# include <stdio.h>2# include <stdlib.h>3# define NULL 04# define OK 15# define ERROR 06# define MAXSIZE 100 /* 矩阵中非零元的最大值 */7# define MAXRC 10 /* 矩阵的最大行值 */89typedef int status ;1011 /********** 稀疏矩阵的行逻辑链接的顺序表存储表示 **********/1213typedef struct /* 非零元的三元组 */14{15int i, j ; /* 非零元的行下标和列下标 */16int e ;17}Triple;1819typedef struct /* 稀疏矩阵的行逻辑链接的顺序表 */20{21 Triple data[MAXSIZE+1]; /* 非零三元组表,data[0]未用,以下定义的数组都是从1开始 */22int rpos[MAXRC+1]; /* 代表各行第一个非零元的序号表,其值为data的下标 */23int mu,nu,tu; /* 矩阵的行数、列数、非零元的个数 */24}RLSMatrix; /* R:row L:logic S:sequence */252627 /********* 基本操作的函数原型的声明 *********/2829status CreateSMatrix_RL(RLSMatrix * matrix);30// 创建一个稀疏矩阵;31// 输入行数、列数,支持乱序输入三元组,并计数;32// 以行为主序进行重新排列,并记录每行起始位置于matrix->rpos[row];33// 若非零元超过 MAXSIZE或行数超过MAXRC,则返回ERROR,否则OK;3435void PrintSMatrix_RL(RLSMatrix * matrix);36// 输入矩阵,打印出矩阵的行数、列数、非零元个数,以及整个矩阵;3738status MultSMatrix_RL(RLSMatrix * M,RLSMatrix *N,RLSMatrix * Q);39// 输入两个稀疏矩阵M和N,并初始化Q,然后计算M*N的值赋给Q;40// 如果M->mu!=N->nu或列数大于MAXRC或者计算出的非零元个数大于MAXSIZE,都返回ERROR,否则OK;41// 计算过程如下:42// 1. 由于矩阵M和Q的行数相等并且C语言以行为主序进行存储,所以以M进行逐行的扫描。
43// 2. 使Q的此行逻辑表的序号等于其非零元个数Q.tu+1,以表示其行的首个元素的序号。
44// 3. 从行中找到M的非零元,并以它的列值为N的行号,对N 进行行的扫描,若存在,则依次计算它们,并把其值累加到一个以N中这个对应非零元的列值为序号的临时数组ctemp[ccol]中。
45// 4. 在M的当前行完成扫描后,将ctemp[ccol]不为0的值,压入到Q矩阵的三元组,累加++Q.tu,若Q.tu大于了MAXSIZE,这返回ERROR。
4647/************ main( ) 函数对矩阵乘法的实现 ************/ 4849void main()50{51 RLSMatrix * M,* N,* Q;52if(!(M=(RLSMatrix *)malloc(sizeof(RLSMatrix)))) 53 exit(ERROR);54if(!(N=(RLSMatrix *)malloc(sizeof(RLSMatrix))))55 exit(ERROR);56if(!(Q=(RLSMatrix *)malloc(sizeof(RLSMatrix))))57 exit(ERROR);58if(CreateSMatrix_RL(M)&&CreateSMatrix_RL(N))59 {60 printf("/nput out M:/n");61 PrintSMatrix_RL(M); /* 打印出M */62 printf("/nput out N:/n");63 PrintSMatrix_RL(N); /* 打印出N */64if(MultSMatrix_RL(M,N,Q)){66 printf("/n/n/n M * N :/n");67 PrintSMatrix_RL(Q); /* 计算结果*/68 }69else70 printf("M.mu and N.nu are not mathing/n");71 }72else73 printf("input error./n");74}757677/*********** 基本操作的算法描述 ****************/7879status CreateSMatrix_RL(RLSMatrix * matrix)80// 创建一个稀疏矩阵;81// 输入行数、列数,支持乱序输入三元组,并计数;82{83int num=0,p,q,min,temp; // 中间变量;84int row;85 printf("input the total row and col:/n");86 scanf("%d%d",&matrix->mu,&matrix->nu); //输入行数、列数;87if(matrix->mu>MAXRC)88return ERROR;89 printf("row col val/n");90scanf("%d%d%d",&matrix->data[num+1].i,&matrix->data[num+1].j,&matrix->data[num+1].e);91while(matrix->data[num+1].i) // 乱序输入三元组;92 {93if(++num>MAXSIZE)94return ERROR;95scanf("%d%d%d",&matrix->data[num+1].i,&matrix->data[num+1].j ,&matrix->data[num+1].e);96 }97 matrix->tu=num; // num的值即为此矩阵的非零元个数;98for(p=1;p<=matrix->tu-1;++p) // 按行为主序依次重新排列非零元99 {100 min=p; // 使较小的行数、列数的元的序号min为当前值p;101for(q=p+1;q<=matrix->tu;++q) // 开始依次比较;102 {103if(matrix->data[min].i>matrix->data[q].i||(matrix->data[min] .i==matrix->data[q].i&&matrix->data[min].j>matrix->data[q].j ))104 min=q; // 在乱序的三元表中,始终保证min是较小的行列数的序号;105 }106 temp=matrix->data[min].i; // 交换行值;matrix->data[min].i=matrix->data[p].i;108 matrix->data[p].i=temp;109 temp=matrix->data[min].j; // 交换列值;110 matrix->data[min].j=matrix->data[p].j;111 matrix->data[p].j=temp;112 temp=matrix->data[min].e; // 交换元素值;113 matrix->data[min].e=matrix->data[p].e;114 matrix->data[p].e=temp;115 }116for(row=1,num=0;row<=matrix->mu;++row) // 记录matrix->rpos[row];117 {118 matrix->rpos[row]=num+1;119while(matrix->data[num+1].i==row)120 ++num;121 }122return OK;123}124// 时间复杂度分析:125// 1. 输入非零元:O(tu); 2. 重新排列(最坏情况下);O(tu*(tu-1)) ; 3. 记录行逻辑表:O(mu)126void PrintSMatrix_RL(RLSMatrix * matrix)127// 输入矩阵,打印出矩阵的行数、列数、非零元个数,以及整个矩阵;128{129int row,col;130int num=0;131 printf("/nrow:%d col:%dnumber:%d/n",matrix->mu,matrix->nu,matrix->tu);132for(row=1;row<=matrix->mu;++row)133 {134for(col=1;col<=matrix->nu;++col)135 {136if(num+1<=matrix->tu&&matrix->data[num+1].i==row&&matrix->da ta[num+1].j==col)137 {138 ++num;139printf("%4d",matrix->data[num].e); /* 当扫描到非零元的行列值与之相等时,输出其值 */140 }141else142 printf("%4d",NULL); /* 没有非零元的地方补0 */143 }144 printf("/n"); /* 每行输入完毕后,换行 */145 }146}147148// 时间复杂度:O(mu*nu).149150151152status MultSMatrix_RL(RLSMatrix * M,RLSMatrix *N,RLSMatrix * Q)153// 输入两个稀疏矩阵M和N,并初始化Q,然后计算M*N的值赋给Q154{155int arow,brow,ccol;156int * ctemp; /* 以N的列值为序号的临时数组 */ 157int tp,p,tq,q; /* 中间变量 */158if(M->nu!=N->mu)159return ERROR;160 Q->mu=M->mu; /* 初始化Q */161 Q->nu=N->nu;162 Q->tu=0;163if(!(ctemp=(int *)malloc((N->nu+1)*sizeof(int)))) /* 动态建立累加器 */164 exit(ERROR);165if(M->tu*N->tu!=0) /* Q是非零矩阵*/166 {167for(arow=1;arow<=M->mu;++arow) /* 逐行扫描 */168 {169for(ccol=1;ccol<=N->nu;++ccol)170 ctemp[ccol]=0; /* 初始化累加器 */171 Q->rpos[arow]=Q->tu+1;172if(arow<M->mu)173 tp=M->rpos[arow+1]; /* tp是M下一行的序号 */174else175 tp=M->tu+1;176for(p=M->rpos[arow];p<tp;++p) /* 从M的当前行找到元素 */{178 brow=M->data[p].j; /* 对应元在N中的行号 */179if(brow<N->mu)180 tq=N->rpos[brow+1]; /* tq是N下一行的行号 */181else182 tq=N->tu+1;183for(q=N->rpos[brow];q<tq;++q) /* 以M的对应元的列号为N的行号进行扫描 */184 {185 ccol=N->data[q].j; /* 提取对应元的列号 */186ctemp[ccol]+=M->data[p].e*N->data[q].e;187 /* 两个对应元的值相乘并累加到以列号为序号的累加器中 */188 }189 }190for(ccol=1;ccol<=Q->nu;++ccol) /* 将此行非零元压缩入Q中 */191 {192if(ctemp[ccol])193 {194if(++Q->tu>MAXSIZE)195return ERROR;196 Q->data[Q->tu].i=arow; 197 Q->data[Q->tu].j=ccol; 198Q->data[Q->tu].e=ctemp[ccol];}200 }201 }202 }203return OK;204}205// 时间复杂度:O(M->mu*(N->nu+M->nu*N->nu+N->nu));status CreateSMatrix_RL(RLSMatrix * matrix)这个函数用2种算法进行了编写:第一种不支持乱序输入,而且输入很麻烦。