实现稀疏矩阵相乘C/C++

实现稀疏矩阵相乘C/C++

1、问题描述:已知稀疏矩阵A(m1,n1)和B(m2,n2),求乘积C(m1,n2)。
A=|3 0 0  7|    B=|4  1|   C=|12 17|
     |0 0 0 -1|         |0  0|        |0    -2|
     |0 2 0  0|         |1 -1|        |0      0|
                             |0   2|
A、B、C的三元组表示法分别为:
A
 ijv
1112
2147
324-1
4322
B
 ijv
1114
2121
3311
432-1
5422
C
 ijv
11112
21217
322-2
2、解决思路:由矩阵乘法规则可知C(i,j) = A(i,1)*B(1,j)+A(i,2)*B(2,j)+....+A(i,n)*B(n,j),即C(i,j)为A的第i行与B的第j列非零元素乘积之和。设置累加器temp[B的列值]保存C矩阵每行的值,结束后将temp中的值赋给C矩阵。
3、定义数据结构:
3.1、稀疏矩阵中节点的定义:
//定义三元组表的节点
typedef struct{
 int i,j;
 int v;
}SPNode;
i,j为行列值,v为此位置的数值。
3.2、稀疏矩阵的定义:
//定义三元组表
typedef struct{
 int mu,nu,tu;
 SPNode data[SMAX];
}SPMatrix;
mu为矩阵行数,nu为矩阵列数,tu为矩阵中非零元素的个数。
4、具体实现:
为了便于B.data寻找第k行第一个非零元素,在此引入num和rpot两个内容。num[k]表示矩阵B中第k行非零元素的个数;rpot[k]表示第k行的第一个非零元素在B.data中的位置。
rpot[1] = 0;
rpot[k] = rpot[k-1]+num[k-1];
矩阵B中的num与rpot的值
col1234
num[col]2020
rpot[col]0224
4.1、初始化。清理一些单元,准备按行顺序存放乘积矩阵。
4.2、求B的num与rpot。
4.3、做矩阵的乘法。
5、代码的具体实现:
/*
 *进行两个稀疏矩阵之间的乘法
*/
#include<stdio.h>
#include<malloc.h>
#define SMAX 1024
//定义三元组表的节点
typedef struct{
 int i,j;
 int v;
}SPNode;
//定义三元组表
typedef struct{
 int mu,nu,tu;
 SPNode data[SMAX];
}SPMatrix;
//进行两个稀疏矩阵之间的乘法,返回值为乘积矩阵
SPMatrix * MulSMatrix(SPMatrix *A,SPMatrix *B){
  SPMatrix *C;
  int p,j,q,i,r,k,t;
  //用于结果的暂存
  int temp[B->nu+1];
  int num[B->mu+1],rpot[B->mu+1];
  C = (SPMatrix*)malloc(sizeof(SPMatrix));
  if(C==NULL){
    printf("申请内存空间失败!\n");
    return NULL;
  }
  //A的列值与B的行值不相等时
  if(A->nu!=B->mu) return NULL;
  C->mu = A->mu;
  C->nu = B->nu;
  //当A或B中的非零元素为0时
  if(A->tu*B->tu==0){
    C->tu = 0;
    return C;
  }
  //计算B矩阵中每行非0元素的个数
  for(i = 1;i<=B->mu;i++)
    num[i] = 0;
  for(i = 0;i<B->tu;i++)
    num[B->data[i].i]++;
  rpot[1] = 0;
  //计算B矩阵中每行首位非0元素的位置
  for(i = 2;i<=B->mu;i++)
    rpot[i] = rpot[i-1]+num[i-1];
   r = 0;//记录当前C矩阵中非0元素的个数
   p = 0;//指示当前A矩阵中非零元素的位置
   //进行矩阵的乘积运算
   for(i = 1;i<=A->mu;i++){
       //将Cij的累加器初始化
        for(j = 1;j<=B->nu;j++)
            temp[j] = 0;
            //求Cij第i行的元素集合
      while(i==A->data[p].i){
        k = A->data[p].j;//获取A矩阵中第p个非零元素的列值
      //确定B中的k行的非零元素在B.data中的下限位置
        if(k<B->mu) t = rpot[k+1];
        else t = B->tu;
        //将B中第k行的每一列非零元素与A中非零元素记录到累加器中
        for(q = rpot[k];q<t;q++){
            j = B->data[q].j;
            temp[j] += A->data[p].v*B->data[q].v;
        }
       p++;
      }
      //将第i行的结果赋值给C矩阵
      for(j = 1;j<=B->nu;j++){
        if(temp[j]!=0){
            C->data[r] = {i,j,temp[j]};
            r++;
        }
      }
   }
   C->tu = r;
   return C;
}
int main(){
    SPMatrix *A,*B,*C;
    int i;
    A = (SPMatrix*)malloc(sizeof(SPMatrix));
    B = (SPMatrix*)malloc(sizeof(SPMatrix));
    printf("请输入A矩阵的行列值与非零元素");
    scanf("%d %d %d",&A->mu,&A->nu,&A->tu);
    printf("请输入A矩阵的非零元素值:\n");
    for(i = 0;i<A->tu;i++)
        scanf("%d %d %d",&A->data[i].i,&A->data[i].j,&A->data[i].v);
    printf("请输入B矩阵的行列值与非零元素");
    scanf("%d %d %d",&B->mu,&B->nu,&B->tu);
    printf("请输入B矩阵阵的非零元素值:\n");
    for(i = 0;i<B->tu;i++)
        scanf("%d %d %d",&B->data[i].i,&B->data[i].j,&B->data[i].v);
    C = MulSMatrix(A,B);
    printf("C->nu:%d,C->mu:%d,C->tu:%d\n",C->mu,C->nu,C->tu);
    for(i = 0;i<C->tu;i++)
        printf("i:%d,j:%d,v:%d\n",C->data[i].i,C->data[i].j,C->data[i].v);
    delete A,B,C;
 return 0;
}
5、算法的时间复杂度:
5.1、求num的时间复杂度为:O(2*B->nu)
5.2、求rpot的时间复杂度为:O(B->mu)
5.3、求temp的时间复杂度为:O(A->mu*B->nu)
5.4、求C中所有元素的时间复杂度为:O(A->tu*B->tu/B->mu)





  • 20
    点赞
  • 65
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
稀疏矩阵转置是将矩阵的行和列交换,但是在稀疏矩阵中,只有非零元素需要交换位置。因此,在转置稀疏矩阵时,需要考虑如何有效地处理非零元素和零元素。以下是一种基于三元组表示法的稀疏矩阵转置算法的实现,其中假设稀疏矩阵已经用三元组表示法存储: ```c++ #include <iostream> using namespace std; #define MAX_SIZE 100 typedef struct { int row; // 行下标 int col; // 列下标 int val; // 非零元素的值 } Triple; typedef struct { Triple data[MAX_SIZE + 1]; // 存储三元组数组 int row, col, num; // 稀疏矩阵的行数、列数和非零元素个数 } Matrix; void Transpose(Matrix &M, Matrix &T) { T.row = M.col; T.col = M.row; T.num = M.num; if (T.num) { int q = 1; for (int col = 1; col <= M.col; col++) { for (int p = 1; p <= M.num; p++) { if (M.data[p].col == col) { T.data[q].row = M.data[p].col; T.data[q].col = M.data[p].row; T.data[q].val = M.data[p].val; q++; } } } } } int main() { Matrix M = { { {1, 1, 5}, {1, 2, 0}, {1, 3, 2}, {2, 2, 6}, {3, 1, 7}, {3, 2, 0}, {3, 3, 3} }, 3, 3, 6 }; Matrix T; Transpose(M, T); cout << "原矩阵:" << endl; for (int i = 1; i <= M.num; i++) { cout << M.data[i].row << " " << M.data[i].col << " " << M.data[i].val << endl; } cout << "转置矩阵:" << endl; for (int i = 1; i <= T.num; i++) { cout << T.data[i].row << " " << T.data[i].col << " " << T.data[i].val << endl; } return 0; } ``` 在上面的代码中,我们首先定义了存储三元组的结构体Triple和存储稀疏矩阵的结构体Matrix,然后定义了一个Transpose函数来实现矩阵转置操作。Transpose函数首先通过交换矩阵的行数和列数来创建一个新的稀疏矩阵T,然后遍历原矩阵M的每一列,将对应的非零元素放入新矩阵T中。最后,函数返回转置后的稀疏矩阵T。 在主函数中,我们首先创建了一个3x3的稀疏矩阵M,然后调用Transpose函数将其转置,并输出原矩阵和转置矩阵的三元组表示形式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值