/*******************行逻辑链接的顺序表*****************/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXSIZE 12500 /// 假设非零元个数最大值为12500
#define MAXRC 12500 ///假设的每行的个数的最大值12500
#define ERROR -1
typedef struct {
int i,j; /// 该非零元的行下标和列下标
int e;
}Triple;
typedef struct {
Triple data[MAXSIZE + 1];///非零元三元组表
int rpos[MAXRC + 1]; ///各行第一个非零元的位置表
/*
以矩阵N为例
rpos[row]指示矩阵N的第row行中第一个非零元在N.data中的序号,则rpos[row+1]-1指示矩阵N的
第row行中最后一个非零元在N.data中的序号,最后一个非零元在N.data中的位置显然就是N.tu了。
也就是说rpos里存的就是各行第一个非零元序号。
*/
int mu,nu,tu; ///矩阵的行数、列数和非零元个数
}RLSMatrix;
void ScanfRLSMatrix(RLSMatrix &M){
int x=0,k=1;
M.tu = 0;
for(int i=1;i<=M.mu;i++){
for(int j=1;j<=M.nu;j++){
scanf("%d",&x);
if(x!=0){
M.data[k].e = x;
M.data[k].i=i;
M.data[k].j=j;
k++;
M.tu++;
}
}
}
///求出rpos的值
int num[MAXSIZE + 1];
if(M.tu){
for(int row=1; row<=M.mu; ++row) num[row]=0; ///清零
for(int t=1; t<=M.tu; ++t) ++num[M.data[t].i]; ///求M中每一列含非零个数
M.rpos[1]=1;
/// 求第col列中第一个非零元在b.data中的序号
for(int row =2; row <= M.mu; ++row) M.rpos[row] = M.rpos[row - 1] + num[row - 1];
}
/**
这个求法在快速转置中也用到了,那个求的是每一列的第一个非零元的恰到位置
这个改一下
*/
}
void PrintfRLSMatrix(RLSMatrix M){
printf("当前矩阵为:\n");
int k=1;
for(int i=1;i<=M.mu;i++){
for(int j=1;j<=M.nu;j++){
if(M.data[k].i==i &&M.data[k].j==j ){
printf("%3d",M.data[k].e);
k++;
}
else printf("%3d",0);
}
puts("");
}
return ;
}
/*************算法5.3************/
int MultSMareix(RLSMatrix M,RLSMatrix N,RLSMatrix &Q){
///求矩阵乘积Q=M*N,采用行逻辑链接存储表示
if(M.nu != N.mu) return ERROR;
Q.mu = M.mu; Q.nu = N.nu; Q.tu=0; ///Q初始化
int ctemp = 0; ///定义累加器
if(M.tu * N.tu != 0){ ///Q是非零矩阵
for(int arow = 1; arow <= M.mu; ++arow){ ///处理M的每一行
int ctemp[500];
memset(ctemp,0,sizeof(ctemp)); ///当前行个元素累加器清零
Q.rpos[arow]=Q.tu+1;
int tp=0; ///定义的矩阵M每一行最后一个非零元的下一个序号
if(arow < M.mu) tp = M.rpos[arow + 1];
else { tp = M.tu + 1; }
/**
前mu行,矩阵M每行最后一个非零元素是M.rpos[arow + 1]-1;
第mu行,矩阵M每行最后一个非零元素是M.tu;
*/
for(int p = M.rpos[arow]; p < tp; ++p){ ///便利当前行的每一个非零元素
int brow = M.data[p].j; ///找到对应元在N中的行号
int t = 0;
///和上面的tp同理,定义矩阵N每一行最后一个非零元的下一个序号
if(brow < N.mu) t = N.rpos[brow + 1];
else { t = N.tu + 1; }
for(int q = N.rpos[brow]; q < t; ++q){
int ccol = N.data[q].j; ///乘积元素在Q中的列号
ctemp[ccol] += M.data[p].e * N.data[q].e;
}//for q
}/// 求得Q中的第crow( = arow)行的非零元
/**
就是M行的第一个非零元,去乘矩阵N的相对应的列q的每一个非零元
结果存储在ctemp数组中。
当矩阵M该行的每一个非零元p都乘完,
此时ctemp数组里存储的就是Q中第一行所有非零元(含零)的结果
*/
for(int i=0;i<=4;i++)
printf("%d ",ctemp[i]);
printf("\n");
for(int ccol = 1; ccol <= Q.nu; ++ccol)
/// 压缩存储该非零元,即把上面求得结果为0的元素去掉
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 arow
}// if
}// MultSMareix
int main()
{
///输入稀疏矩阵M
RLSMatrix M;
printf("请输入稀疏M的矩阵行mu和列nu:");
scanf("%d%d",&M.mu,&M.nu);
ScanfRLSMatrix(M);
PrintfRLSMatrix(M);
///输入稀疏矩阵N
RLSMatrix N;
printf("请输入稀疏N的矩阵行mu和列nu:");
scanf("%d%d",&N.mu,&N.nu);
ScanfRLSMatrix(N);
PrintfRLSMatrix(N);
RLSMatrix Q;
///测试行逻辑链接存储的矩阵相乘
MultSMareix(M,N,Q);
printf("结果是:\n");
PrintfRLSMatrix(Q);
return 0;
}