稀疏矩阵的乘法

Description

计算两个稀疏矩阵的乘法

Input

首先输入第一个矩阵的行数和列数,再输入该矩阵的三元组形式,以0 0 0结束
然后输入第二个矩阵的行数和列数,再输入该矩阵的三元组形式,以0 0 0结束

Output

输出相加后的矩阵三元组。

  • Sample Input 
    3 3
    1 1 1
    2 2 2
    2 3 4
    3 1 -4
    0 0 0
    3 3
    1 3 -2
    2 3 -5
    3 1 8
    3 2 -6
    0 0 0
  • Sample Output
    1 3 -2
    2 1 32
    2 2 -24
    2 3 -10
    3 3 8
#include<stdio.h>  
#include<stdlib.h>  
#include<malloc.h>  
  
#define MAXSIZE 1024  
  
typedef struct {  
  int  i,j;  
  int  e;  
}Triple;  
  
typedef struct  {  
  Triple data[MAXSIZE];  
  int mu,nu,tu;  
}TSMatrix;  
TSMatrix *Create(TSMatrix *A)  
{  
    int m,n,i;  
    scanf("%d %d",&m,&n);  
    A->mu=m;  
    A->nu=n;  
    A->tu=0;  
    for(i=0;;i++)  
    {  
        scanf("%d %d %d",&A->data[i].i,&A->data[i].j,&A->data[i].e);  
        if(A->data[i].i==0&&A->data[i].j==0&&A->data[i].e==0)  
            break;  
        A->tu++;  
    }  
    return A;  
}  
void output(TSMatrix *M)  
{  
    int i;  
    for(i=0;i<M->tu;i++)  
    {  
        printf("%d %d %d\n",M->data[i].i,M->data[i].j,M->data[i].e);  
    }  
}  
TSMatrix * MultiTSM(TSMatrix *A,TSMatrix *B)  
{  
      TSMatrix *C;  
      int p,j,q,i,r,k,t;  
      int temp[B->nu+1];  
      int cnt[B->mu+1],num[B->mu+1];  
      C = (TSMatrix*)malloc(sizeof(TSMatrix));  
      if(A->nu!=B->mu) return NULL;  
      C->mu = A->mu;  
      C->nu = B->nu;  
      if(A->tu*B->tu==0)  
      {  
        C->tu = 0;  
        return C;  
      }  
      for(i = 1;i<=B->mu;i++)  
        cnt[i] = 0;  
      for(i = 0;i<B->tu;i++)  
        cnt[B->data[i].i]++;  
      num[1] = 0;  
      for(i = 2;i<=B->mu;i++)  
        num[i] = num[i-1]+cnt[i-1];  
       r = 0;//记录当前C矩阵中非0元素的个数  
       p = 0;//指示当前A矩阵中非零元素的位置  
       //进行矩阵的乘积运算  
       for(i = 1;i<=A->mu;i++)  
       {  
            for(j = 1;j<=B->nu;j++)  
                temp[j] = 0;  
          while(i==A->data[p].i)  
          {  
            k = A->data[p].j;  
  
            if(k<B->mu) t = num[k+1];  
            else t = B->tu;  
            for(q = num[k];q<t;q++)  
            {  
                j = B->data[q].j;  
                temp[j] += A->data[p].e*B->data[q].e;  
            }  
           p++;  
          }  
          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()  
{  
    TSMatrix *A;  
    TSMatrix *B;  
    TSMatrix *C;  
    A = (TSMatrix*)malloc(sizeof(TSMatrix));  
    B = (TSMatrix*)malloc(sizeof(TSMatrix));  
    A=Create(A);  
    B=Create(B);  
    C=MultiTSM(A,B);  
    output(C);  
    return 0;  
}  
快速乘法如下:
#include <iostream>
#include <stdio.h>
using namespace std;

#define   TRUE                    1
#define   FALSE                    0
#define   OK                    1
#define   ERROR                    0
#define   OVERFLOW                -2
#define   INFEASIBLE            -1

#define MAXSIZE 12500
#define MAXRC 100

#define      ElemType int

typedef struct
{
    int i,j;//行,列
    ElemType e;//元素值
}Triple;

typedef struct
{
    Triple  data[MAXSIZE+1];
    int        rpos[MAXRC+1];//每行第一个非零元素在data数组中的位置
    int        mu,nu,tu;//行数,列数,元素个数
}RLSMatrix;

int MultSMatrix(RLSMatrix M, RLSMatrix N, RLSMatrix &Q)
{
    if(M.nu != N.mu)//矩阵M的列数与矩阵N的行数不等,则不能做矩阵乘运算
        return ERROR;
    Q.mu = M.mu;
    Q.nu = N.nu;
    Q.tu = 0;
    if(M.tu * N.tu == 0)//其中任意矩阵的元素个数为零,则不能做乘运算
        return ERROR;
    else
    {
        int arow;
        int ccol;
        for(arow=1; arow<=M.mu; arow++)//处理矩阵M的每一行
        {
            int ctemp[MAXRC+1] ={};
            Q.rpos[arow] = Q.tu + 1;
            int tp;
            if(arow < M.mu)
                tp = M.rpos[arow+1];//获取矩阵M的下一行第一个非零元素在data数组中位置
            else
                tp = M.tu+1;//若当前行是最后一行,则取最后一个元素+1
            int p;
            int brow;
            for(p=M.rpos[arow]; p<tp; p++)//对当前矩阵M中的每一个非零元素,在矩阵N中找到对应可乘元素
            {
                brow = M.data[p].j;
                int t;
                if(brow < N.mu)
                    t = N.rpos[brow+1];
                else
                    t = N.tu+1;
                int q;
                //int ccol;
                for(q=N.rpos[brow]; q<t; q++)
                {
                    ccol = N.data[q].j;
                    ctemp[ccol] += M.data[p].e * N.data[q].e;
                }
            }
            for(ccol=1; ccol<=Q.nu; ccol++)
            {
                if(ctemp[ccol])
                {
                    if(++Q.tu > MAXSIZE)
                        return ERROR;
                    Q.data[Q.tu].e = ctemp[ccol];
                    Q.data[Q.tu].i = arow;
                    Q.data[Q.tu].j = ccol;
                }
            }
        }
        return OK;
    }
}

void Findrpos(RLSMatrix &M)
{
    int row;
    int num[100];
    for (row = 1; row <= M.mu; row++)
        num[row] = 0;                 //num数组的初始化
    for (int t = 1; t <= M.tu; t++)
        ++num[M.data[t].i];         //求M中每一行含有的非零元个数
    M.rpos[1] = 1;
    for (row = 2; row <= M.mu; row++)
        M.rpos[row] = M.rpos[row - 1] + num[row - 1];
}

void PrintMartix(RLSMatrix &M)
{
    int k;
    for(k=1; k<=M.tu; k++)
        cout<<M.data[k].i << " "<<M.data[k].j << " "<< M.data[k].e<<endl;
}

int main(int argc, char* argv[])
{
    RLSMatrix M,N,T;
    int m,n;
    scanf("%d %d",&m,&n);
    M.mu = m;
    M.nu = n;
    for(int i = 1;;i++)
    {
        scanf("%d %d %d",&M.data[i].i,&M.data[i].j,&M.data[i].e);
        if(M.data[i].i==0&&M.data[i].j==0&&M.data[i].e==0)break;
        M.tu++;
    }
    int x,y;
    scanf("%d %d",&x,&y);
    N.mu = x;
    N.nu = y;
    for(int i = 1;;i++)
    {
        scanf("%d %d %d",&N.data[i].i,&N.data[i].j,&N.data[i].e);
        if(N.data[i].i==0&&N.data[i].j==0&&N.data[i].e==0)break;
        N.tu++;
    }
    Findrpos(M);
    Findrpos(N);
    MultSMatrix(M,N,T);
    PrintMartix(T);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值