矩阵乘法

本文详细介绍了如何通过三元组表示法实现稀疏矩阵的乘法运算,包括矩阵的构造、乘法处理及结果展示。该算法适用于非零元素较少的大型矩阵,能有效节省存储空间并提高运算效率。

/*
矩阵乘法 

逻辑关系较强,需要细细体会
*/

#include <iostream>
using namespace std;
#define MAX 100
#define HMAX 100

typedef struct node{
    int x,y;
    int value;
}SRC;

typedef struct node_1{
    SRC arr[MAX];
    int cols[HMAX];  /*矩阵中的每一行的第一个非零元素在三元组中的位置*/
    int mu,nu,tu;  /*分别表示矩阵的行数 列数和总的非零元素的数目*/
}SRCD;

void Create(int a[][4],int m,int n,SRCD* &srcd)
{
    /*遍历矩阵  构造三元组  同时存储相应的矩阵的每一行的相应的第一个非零元素在三元组中的位置*/
    if(a== NULL)  return ;
    int k=0;
    int flag ;
    srcd->tu  =0 ;
    for(int i=1;i<=m;i++){
        flag = 0;
        srcd->cols[i]=0;
        for(int j=1;j<=n;j++){
            if(a[i][j]){
                k++;
                if(flag == 0){
                    srcd->cols[i] = k;
                    flag =1;
                }
                srcd->arr[k].x = i;
                srcd->arr[k].y = j;
                srcd->arr[k].value = a[i][j];
                srcd->tu++;
            }
        }
    }
    cout<<sizeof(srcd->cols)/sizeof(int)<<endl;
    srcd->mu = m;
    srcd->nu = n;
}

void DisplaySrcd(SRCD* srcd)
{
    /*遍历三元组  显示三元组中的每一个三语组的x y value*/
    if (srcd == NULL)  return ;
    for(int i=1;i<=srcd->tu;i++){
        cout<<srcd->arr[i].x<<" "<<srcd->arr[i].y<<" "<< srcd->arr[i].value<<endl;
    }
}

void Deal(SRCD* srcd_1,SRCD* srcd_2,SRCD* &dest)
{
    /*求解矩阵的乘法*/
    if( srcd_1 == NULL || srcd_2 == NULL )  return ;
    if( srcd_1->nu != srcd_2->mu )  return ;
    if( srcd_1->tu * srcd_2->tu ){
        dest->mu = srcd_1->mu;
        dest->nu = srcd_2->nu;
        dest->tu = 0;
        int* temp = new int[srcd_2->nu+1];
        int tp;
        int h;
        int s_l;
        int t;
        int col;
        for( int i=1;i<=srcd_1->mu;i++){    /*遍历被乘矩阵的每一行*/
            for( int j=1;j<=srcd_2->nu;j++){      /*初始化结矩阵的每一行的每一个元素的值*/
                temp[j]=0;
            }
            dest->cols[i] = dest->tu+1;
            if( i<srcd_1->mu ) tp = srcd_1->cols[i+1];   /*找到被乘矩阵的每一行的遍历上边界*/
            else{
                tp = srcd_1->tu+1;                       /*当被乘矩阵到达最后的时候将遍历的商界设为被乘矩阵的最大三语组的数目加一 从而得到被乘矩阵的最后一行的遍历的上界*/
            }
            for( int k=srcd_1->cols[i];k<tp;k++ ){       /*去的被乘矩阵的每一行的第一个非零三元组开始位置  也就是找到北城矩阵的每一行便利的下边界*/
                s_l = srcd_1->arr[k].y;                  
                if( s_l < srcd_2->mu ) t = srcd_2->cols[s_l+1];   /*根据北城矩阵相应的每一行的每一个非零元素从而确定相应的行  这就是陈矩阵的下边界*/
                else{
                    t = srcd_2->tu+1;                    /*确定成矩阵的相应行的上边界*/
                }
                for(int h = srcd_2->cols[s_l];h<t;h++){       /*根据成矩阵的遍历边界进行相应的遍历  求得结果矩阵的第i行的每一个节点的结果*/
                    col = srcd_2->arr[h].y;
                    temp[col] += srcd_1->arr[k].value * srcd_2->arr[h].value;
                }
            }
            for( int j = 1;j <= dest->nu;j++){   /*使用三元组存储结果矩阵相应的行的每一个非零元  不难发现最终的结果矩阵的行受到被乘矩阵的影响  然而列受到相应的乘矩阵的影响  这也正是矩阵的乘法的原理*/
                if(temp[j]){
                    dest->tu++;
                    dest->arr[dest->tu].x = i;
                    dest->arr[dest->tu].y = j;
                    dest->arr[dest->tu].value = temp[j];
                }
            }
        }
    }
}

int main()
{
    int a[4][4], b[4][4];
    for(int i=1;i<=3;i++){
        for(int j=1;j<=3;j++)
        cin>>a[i][j];
    }
    for(int i=1;i<=3;i++){
        for(int j=1;j<=3;j++)
        cin>>b[i][j];
    }
    SRCD *srcd_1 = NULL ,*srcd_2 = NULL,*dest = NULL;
    srcd_1= new SRCD;
    srcd_2= new SRCD;
    dest = new SRCD;
    Create(a,3,3,srcd_1);   /*创建被乘矩三元组*/
    cout<<srcd_1->tu<<endl;
    Create(b,3,3,srcd_2);   /*创建乘矩阵三元组*/
    cout<<srcd_2->tu<<endl;
    DisplaySrcd(srcd_1);    /*遍历被乘矩阵三元组*/
    cout<<"-------------------------我是分割线-----------------------"<<endl;
    DisplaySrcd(srcd_2);    /*遍历乘矩阵三元组*/
    cout<<"-------------------------我是分割线-----------------------"<<endl;
    Deal(srcd_1,srcd_2,dest);     /*求解矩阵的乘法*/
    DisplaySrcd(dest);      /*遍历最终的结果矩阵的三元组*/
    system("pause");
    return 0;
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值