稀疏矩阵乘法(C语言)

在这里插入图片描述
在这里插入图片描述

代码:

#include<stdio.h>
#include<stdlib.h>

#define MAXSIZE 1000
typedef struct{
int row;//第几行
int col;//第几列
int e;//存储的值
}Triple;

typedef struct
{
    Triple data[MAXSIZE];
    int m,n,len;//稀疏矩阵的行,列,非零元素的个数
}TSMatrix;

void createTSMatrix(TSMatrix *A)//创建矩阵
{    int i=0;     //data【0】未用
    scanf("%d?%d",&A->m,&A->n);
    int flag = 1;
    int a,b,c;
    char c1,c2,c3;
    while(flag)
    {
        scanf("%d?%d?%d",&a,&b,&c);


          if(a==0&&b==0&&c==0)
            break;
            i++;
          A->data[i].row=a;
          A->data[i].col=b;
          A->data[i].e=c;


    }
    A->len=i;
}

void printMatrix(TSMatrix *B)//输出矩阵
{
    for(int i=1;i<=B->len;i++)
    {
        printf("%d?%d?%d\n",B->data[i].row,B->data[i].col,B->data[i].e);
    }

}

void MulTSMatrix(TSMatrix *A,TSMatrix *B,TSMatrix *C)//矩阵相乘
{
    C->len=0;
    int p,q,x,cnt;
    int i1,j1;
    int sum;
    cnt=1;
    for(int i=1;i<=A->m;i++)
    {

        for(int j=1;j<=B->n;j++)//遍历每行每列
        {
           sum=0;
            for(int k=1;k<=A->n;k++)//每个行与每个列单个数的遍历
            {    p=0;q=0;
                for(i1=1;i1<=A->len;i1++){  //遍历A找符合i行k列的数
                    if(A->data[i1].row==i&&A->data[i1].col==k) p=A->data[i1].e;
                   }
                   for(j1=1;j1<=B->len;j1++){//遍历B找符合k行j列的数
                    if(B->data[j1].row==k&&B->data[j1].col==j) q=B->data[j1].e;
                   }
                sum=sum+(p*q);

            }
            if(sum!=0) {cnt++;
            C->data[cnt].e=sum;
            C->data[cnt].row=i;
            C->data[cnt].col=j;}

        }
    }
    C->len=cnt;

}

int main()
{
    TSMatrix A,B,C;
    createTSMatrix(&A);
    createTSMatrix(&B);
    MulTSMatrix(&A,&B,&C);
    printMatrix(&C);
    return 0;

}

第二个程序:
首先将矩阵每行的非0元个数记下来,那么矩阵每行第一个非0元在三元表的位置就是上一行非0元个数加上上一行首个非0元位置之和。这样就可以不用遍历三元表,就可以快速找到相应的三元组表元素。相乘时先将结果存入一个数组中,然后取其中非0元素存入新的三元组表。最后输出新三元组表即可。

#include <stdio.h>
#include <stdlib.h>

struct Triple
{
    int ti;
    int tj;
    int value;
};

struct tripleList
{
    struct Triple T[2000];
    int li;
    int lj;
    int ln;
};

void createNewTripleList (struct tripleList *list);
void getRowPot (struct tripleList *list,int rowPot[]);
void clear (struct tripleList *list);
void printTripleList (struct tripleList *list);
void mul (struct tripleList *list1,struct tripleList *list2,struct tripleList *list3,int rowPot1[],int rowPot2[]);
void run ();

int main()
{
    run ();

    return 0;
}

void run ()
{
    int rowPot1[2000]={0},rowPot2[2000]={0};
    struct tripleList list1,list2,list3;

    createNewTripleList (&list1);//输入两个三元组表
    createNewTripleList (&list2);
    getRowPot (&list1,rowPot1);//得到它们的位置数组
    getRowPot (&list2,rowPot2);

    mul (&list1,&list2,&list3,rowPot1,rowPot2);//相乘
    printTripleList (&list3);//输出
}
void createNewTripleList (struct tripleList *list)
{
    int i=0,a,b,c;
    scanf ("%d?%d",&(list->li),&(list->lj));//输入行数列数
    while (1)
    {
        scanf ("%d?%d?%d",&a,&b,&c);//输入行 列 数据
        if (a==0&&b==0&&c==0)//都为0时停止输入
        {
            break;
        }
        list->T[i].ti=a-1;//赋值,因为题目输入的行列数据是从1开始的,这里将它转为以0开始,最后输出时在加上1
        list->T[i].tj=b-1;
        list->T[i].value=c;
        i++;
    }
    list->ln=i;//得到三元组表元素个数
}

void printTripleList (struct tripleList *list)
{
    int i;
    for (i=0;i<=list->ln-1;i++)//输出三元组表的所有元素
    {
        printf ("%d?%d?%d\n",list->T[i].ti+1,list->T[i].tj+1,list->T[i].value);
    }
}

void mul (struct tripleList *list1,struct tripleList *list2,struct tripleList *list3,int rowPot1[],int rowPot2[])
{
    int i,j,k,l,no,max,n,len1,len2,A[2000]={0};
    list3->li=list1->li;//得到行列
    list3->lj=list2->lj;
    for (i=0,n=0;i<=list1->li-1;i++)//遍历第一个矩阵的行
    {
        len1=rowPot1[i+1]-1;//得到这一行的所有非0元在三元组表的位置区间的右端
        for (j=rowPot1[i],max=0;j<=len1;j++)//在这一行所有非0元在三元组表中的位置区间中遍历
        {
            len2=rowPot2[list1->T[j].tj+1]-1;//得到第二个矩阵中列号与上一个for中的行号相等的所有非0元在三元组表的位置区间的最左端
            for (k=rowPot2[list1->T[j].tj];k<=len2;k++)//在这一行所有非0元在三元组表中的位置区间遍历
            {
                no=list2->T[k].tj;
                A[no]+=list1->T[j].value*list2->T[k].value;//在数组中添加相乘结果
                max=no>max?no:max;
            }
        }
        for (l=0;l<=max;l++)
        {
            if (A[l]!=0)//将非0的结果存入新的三元组表中
            {
                list3->T[n].ti=list1->T[j-1].ti;
                list3->T[n].tj=l;
                list3->T[n].value=A[l];
                ++n;
                A[l]=0;
            }
        }
    }
    list3->ln=n;//得到新三元组表的元素个数
}

void getRowPot (struct tripleList *list,int rowPot[])
{
    int n[2000]={0};
    int i,pre1=0,pre2=0;
    for (i=0;i<=list->ln-1;i++)//得到矩阵每行的非0元个数
    {
        (n[list->T[i].ti])++;
    }
    for (i=0;i<=list->li;i++)
    {
        rowPot[i]=pre1+pre2;//本行第一个非0元素在三元组表中的位置,上一行的非0元个数加上上一行第一个非0元在三元组表中的位置
        pre1=n[i];
        pre2=rowPot[i];
    }
}

运行截图:

在这里插入图片描述

稀疏矩阵乘法是一种优化的矩阵乘法算法,适用于矩阵中大部分元素为0的情况。下面是用C语言表示稀疏矩阵乘法的完整代码: ``` #include <stdio.h> #define MAX_SIZE 100 typedef struct { int row; int col; int val; } Triple; void sparse_matrix_multiply(Triple a[], Triple b[], Triple c[]) { int m = a[0].row, n = b[0].col, t = 0; int row_terms[MAX_SIZE], bstart[MAX_SIZE + 1]; int i, j, k, sum; // 计算b中每行第一个非零元素的位置 for (i = 1; i <= n; i++) { bstart[i] = 0; } for (i = 1; i <= b[0].val; i++) { bstart[b[i].col]++; } for (i = 2; i <= n; i++) { bstart[i] += bstart[i - 1]; } // 计算a中每行第一个非零元素的位置 for (i = 1; i <= m; i++) { row_terms[i] = 0; } for (i = 1; i <= a[0].val; i++) { row_terms[a[i].row]++; } for (i = 2; i <= m; i++) { row_terms[i] += row_terms[i - 1]; } // 稀疏矩阵乘法 for (i = 1; i <= m; i++) { for (j = 1; j <= n; j++) { sum = 0; for (k = row_terms[i]; k < row_terms[i + 1]; k++) { while (bstart[a[k].col] <= bstart[a[k].col + 1]) { if (b[bstart[a[k].col]].row == j) { sum += a[k].val * b[bstart[a[k].col]].val; break; } bstart[a[k].col]++; } } if (sum != 0) { t++; c[t].row = i; c[t].col = j; c[t].val = sum; } } } // 存储结果 c[0].row = m; c[0].col = n; c[0].val = t; } int main() { Triple a[] = {{3, 3, 3}, {1, 1, 1}, {1, 2, 2}, {2, 2, 3}, {3, 3, 4}}; Triple b[] = {{3, 3, 3}, {1, 2, 1}, {2, 1, 2}, {3, 3, 3}}; Triple c[MAX_SIZE]; int i; sparse_matrix_multiply(a, b, c); printf("Result:\n"); for (i = 1; i <= c[0].val; i++) { printf("%d %d %d\n", c[i].row, c[i].col, c[i].val); } return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mcl19909949541

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值