矩阵(稀疏矩阵)的压缩存储(二)



来源:http://blog.163.com/zhoumhan_0351/blog/static/39954227201001232725635/


上一节中我们讨论的是稀疏矩阵的转置,现在我们讨论稀疏矩阵的相乘,相加,相减。如果预先知道不是稀疏矩阵,则用二维数组相乘法就可以了。如果是,则我们用来存储矩阵的结构称之为行逻辑连接的顺序表,就是加入一个行表来记录稀疏矩阵中每行的非零元素在三元组表中的起始位置。

一、算法思想

M.dataN.data中找到相应的各对元素进行相乘即可。此时矩阵的存储结构是

36、矩阵(稀疏矩阵)的压缩存储(二) - 墨涵 - 墨涵天地

         在此,我们引入rpos[row]用来指示矩阵N的第row行中第一个非零元在N.data中的序号,则rpos[row+1]-1指示矩阵的第row行中最后一个非零元在N.data中的序号。而最后一行中最后一个非零元在N.data的位置就是N.tu了。
36、矩阵(稀疏矩阵)的压缩存储(二) - 墨涵 - 墨涵天地
36、矩阵(稀疏矩阵)的压缩存储(二) - 墨涵 - 墨涵天地

     如上图中,Nrpos值为:

36、矩阵(稀疏矩阵)的压缩存储(二) - 墨涵 - 墨涵天地

二、C语言描述

36、矩阵(稀疏矩阵)的压缩存储(二) - 墨涵 - 墨涵天地

36、矩阵(稀疏矩阵)的压缩存储(二) - 墨涵 - 墨涵天地36、矩阵(稀疏矩阵)的压缩存储(二) - 墨涵 - 墨涵天地36、矩阵(稀疏矩阵)的压缩存储(二) - 墨涵 - 墨涵天地

36、矩阵(稀疏矩阵)的压缩存储(二) - 墨涵 - 墨涵天地

三、C语言实现

#include "stdio.h"

#include "stdlib.h"

#define MAXSIZE 12500

#define MAXRC   100

#define OK 1

#define ERROR -1

typedef int ElemType;

typedef int Status;

typedef struct

{

int i,j;

ElemType e;

}Triple;

typedef struct

{

Triple data[MAXSIZE+1];

int rpos[MAXRC+1];//各行第一个非零元的位置表

int mu,nu,tu;   //矩阵行数,列数和非0元个数

}RLSMatrix;

int cpot[MAXSIZE+1],num[MAXSIZE+1];

Status CreateSMatrix(RLSMatrix &M)

 { // 创建稀疏矩阵M

   int i;

   Triple T;

   Status k;

   printf("请输入矩阵的行数,列数,非零元素数:(Separated by commas)\n");

   scanf("%d,%d,%d",&M.mu,&M.nu,&M.tu);

   M.data[0].i=0; // 为以下比较做准备

   for(i=1;i<=M.tu;i++)

   {

     do

     {

       printf("请按行序顺序输入第%d个非零元素所在的行(1~%d),列(1~%d),元素值:",i,M.mu,M.nu);

       printf("the 3 num Separated by commas\n");

          scanf("%d,%d,%d",&T.i,&T.j,&T.e);

       k=0;

       if(T.i<1||T.i>M.mu||T.j<1||T.j>M.nu) // 行、列超出范围

         k=1;

       if(T.i<M.data[i-1].i||T.i==M.data[i-1].i&&T.j<=M.data[i-1].j) // 没有按顺序输入非零元素

         k=1;   //&&优先级比||高

     }while(k); // 当输入有误,重新输入

     M.data[i]=T;

   }

   for(i=1;i<=M.tu;i++) // 计算rpos[]

     if(M.data[i].i>M.data[i-1].i)

       for(T.i=0;T.i<M.data[i].i-M.data[i-1].i;T.i++)

         M.rpos[M.data[i].i-T.i]=i;

   for(i=M.data[M.tu].i+1;i<=M.mu;i++) // 给最后没有非零元素的几行赋值

     M.rpos[i]=M.tu+1;

   return OK;

 }//CreateSMatrix

void DestroySMatrix(RLSMatrix &M)

 { // 销毁稀疏矩阵M(使M为0行0列0个非零元素的矩阵)

   M.mu=0;

   M.nu=0;

   M.tu=0;

 }//DestroySMatrix

void PrintSMatrix(RLSMatrix M)

 { // 输出稀疏矩阵M

   int i;

   printf("%d行%d列%d个非零元素。\n",M.mu,M.nu,M.tu);

   printf("行  列  元素值\n");

   for(i=1;i<=M.tu;i++)

     printf("%2d%4d%8d\n",M.data[i].i,M.data[i].j,M.data[i].e);

   for(i=1;i<=M.mu;i++)

     printf("第%d行的第一个非零元素是本矩阵第%d个元素\n",i,M.rpos[i]);

 }//PrintSMatrix

Status MultSMatrix(RLSMatrix M,RLSMatrix N,RLSMatrix &Q)

 { // 求稀疏矩阵乘积Q=M*N。

   int arow,brow,p,q,ccol,ctemp[MAXRC+1];

   if(M.nu!=N.mu) // 矩阵M的列数应和矩阵N的行数相等

     return ERROR;

   Q.mu=M.mu; // Q初始化

   Q.nu=N.nu;

   Q.tu=0;

   M.rpos[M.mu+1]=M.tu+1; // 为方便后面的while循环临时设置

   N.rpos[N.mu+1]=N.tu+1;

   if(M.tu*N.tu!=0) // M和N都是非零矩阵

   {

     for(arow=1;arow<=M.mu;++arow)

     { //从M的第一行开始,到最后一行,arow是M的当前行

       for(ccol=1;ccol<=Q.nu;++ccol)

         ctemp[ccol]=0; //Q的当前行的各列元素累加器清零

       Q.rpos[arow]=Q.tu+1; //Q当前行的第1个元素位于上1行最后1个元素之后

       for(p=M.rpos[arow];p<M.rpos[arow+1];++p)

       { // 对M当前行中每一个非零元

         brow=M.data[p].j; //找到对应元在N中的行号(M当前元的列号)

         for(q=N.rpos[brow];q<N.rpos[brow+1];++q)

         {

           ccol=N.data[q].j; //乘积元素在Q中列号

           ctemp[ccol]+=M.data[p].e*N.data[q].e;

         }//for

       } //求得Q中第arow行的非零元

       for(ccol=1;ccol<=Q.nu;++ccol) //压缩存储该行非零元

         if(ctemp[ccol])

         {

           if(++Q.tu>MAXSIZE)

             return ERROR;

           Q.data[Q.tu].i=arow;

           Q.data[Q.tu].j=ccol;

           Q.data[Q.tu].e=ctemp[ccol];

         }//if

     }//for

   }//if

   return OK;

 }//MultSMatrix

int main()

{

RLSMatrix M,N,Q;

CreateSMatrix(M);

CreateSMatrix(N);

MultSMatrix(M,N,Q);

PrintSMatrix(Q);

DestroySMatrix(M);

DestroySMatrix(N);

DestroySMatrix(Q);

return OK;

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值