问题 I: 算法5-3:带行向量的稀疏矩阵相乘(附加代码模式)

博客要求使用带行向量的三元组法存储的稀疏矩阵实现矩阵乘法。给出了输入输出格式、样例,还提及数据范围与提示,包括vector基本用法及代码框架,让读者根据注释完成部分函数代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

请使用带行向量的三元组法存储的稀疏矩阵,实现矩阵乘法。
本题为附加代码模式,以下代码会自动附加在提交的代码后面,请同学们注释之后提交

// 两个三元组法表示的矩阵相乘
TriMatrix Mul(const TriMatrix& M1, const TriMatrix& M2){
    TriMatrix M;
    M.mu = M1.mu;  M.nu = M2.nu; M.tu = 0;
    for(int i=0;i<M1.tu;i++){
        int c = M1.data[i].c;
        for(int j=M2.rpos[c];j<M2.rpos[c]+M2.rsum[c];j++){
            AddNode(M,M1.data[i].r,M2.data[j].c,M1.data[i].v * M2.data[j].v);
        }
    }
    return M;
}

int main(){
    // freopen("/config/workspace/answer/test.in","r",stdin);
    // freopen("/config/workspace/answer/test.out","w",stdout);
    TriMatrix M1, M2;
    InputMatrix(M1);
    InputMatrix(M2);
    CalcRPosMatrix(M1);
    CalcRPosMatrix(M2);
    // PrintMatrix(M1);
    // PrintMatrix(M2);

    TriMatrix M = Mul(M1,M2);
    CalcRPosMatrix(M);
    // PrintMatrix(M);
    PrintMatrixArray(M);
    return 0;
}

输入格式

输入的第一行是两个整数r1和c1(r1<200, c1<200, r1*c1 <= 12500),分别表示一个包含很多0的稀疏矩阵的行数和列数。接下来有r1行,每行有c1个整数,用空格隔开,表示第一个稀疏矩阵的各个元素。 之后的一行有两个整数r2和c2(c1=r2<200, c2<200, r2*c2 <= 12500),分别表示一个包含很多0的稀疏矩阵的行数和列数。接下来有r2行,每行有c2个整数,用空格隔开,表示第二个稀疏矩阵的各个元素。

输出格式

输出两个矩阵的乘积。输出共有r1行,每行有c2个整数,每个整数后输出一个空格。请注意行尾输出换行。

输入样例

4 5
0 0 0 69 78
0 0 5 0 0
0 0 0 0 0
0 91 2 0 82
5 6
0 18 0 0 0 0
0 0 67 0 0 0
0 0 0 0 0 41
0 0 47 62 0 0
0 0 0 0 0 35

输出样例  

0 0 3243 4278 0 2730 
0 0 0 0 0 205 
0 0 0 0 0 0 
0 0 6097 0 0 2952 

数据范围与提示 

1)题目用vector存储行向量,非零元数据,有关vector的使用方法,请通过搜索引擎查找资料,本题用到的两个vector基本用法如下:
1、在vector后面追加一个元素  

        M.data.push_back({r,c,v});

2、在vector中间index下标所在位置插入一个元素

        vector<TriNode>::iterator it = M.data.begin();

        for(int i=0;i<index;i++) ++it;

        M.data.insert(it,{r,c,v});

(2)本题的代码框架如下,请同学根据注释完成部分函数的代码

#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;

// 三元组结构体
struct TriNode{
    // 行,列,值
    int r,c,v;
};
// 输出单个非零元
void PrintTriNode(const TriNode& T){
    cout << T.r << " " << T.c << " " << T.v << endl;
}
// 稀疏矩阵
struct TriMatrix{
    // 行数,列数,非零元个数
    int mu,nu,tu;
    vector<TriNode> data; // 三元组法表示的非零元
    vector<int> rsum;  // 每行非零元个数
    vector<int> rpos;  // 行向量
};

void InputMatrix(TriMatrix& M){
    cin >> M.mu >> M.nu;
    M.tu = 0;
    for(int i=0;i<M.mu;i++){
        for(int j=0;j<M.nu;j++){
            int t; cin >> t;
            if(t != 0){
                M.data.push_back({i,j,t});
                M.tu++;
            }
        }
    }
}
// 计算三元组法表示的稀疏矩阵的每行非零元个数和行向量
void CalcRPosMatrix(TriMatrix& M){
    // 第一步:计算每行非零元个数
    // 第二步:计算行向量
    // 请同学们完成这个函数的功能
}
// 输出三元组法表示的稀疏矩阵,用于辅助调试
void PrintMatrix(const TriMatrix& M){
    cout << "================================================" << endl;
    cout << "mu=" << M.mu << ",nu=" << M.nu << ",tu=" << M.tu << endl;
    for(int i=0;i<M.tu;i++){
        PrintTriNode(M.data[i]);
    }
    cout << "rsum:";
    for(int i=0;i<M.mu;i++) cout << M.rsum[i] << " ";
    cout << endl;
    cout << "rpos:";
    for(int i=0;i<M.mu;i++) cout << M.rpos[i] << " ";
    cout << endl;
    cout << "================================================" << endl;
}
// 用二维数组的形式输出三元组法表示的稀疏矩阵
void PrintMatrixArray(const TriMatrix& M){
    int array[M.mu][M.nu] = {0};
    for(int i=0;i<M.mu;i++){
        for(int j=0;j<M.nu;j++){
            array[i][j] = 0;
        }
    }
    for(int i=0;i<M.tu;i++){
        array[M.data[i].r][M.data[i].c] = M.data[i].v;
    }
    for(int i=0;i<M.mu;i++){
        for(int j=0;j<M.nu;j++){
            cout << array[i][j] << " ";
        }
        cout << endl;
    }
}
// 三元组法表示的稀疏矩阵,添加非零元
void AddNode(TriMatrix& M, int r, int c, int v){
    // 1、如果已存在行列相同的节点,追加值
    // 2、否则,将该非零元按行优先的顺序找到合适的位置,插入节点
    // 请同学们完成这个函数的功能
}


// !!!!!以下代码会自动附加,请同学注释之后提交

// 两个三元组法表示的矩阵相乘
TriMatrix Mul(const TriMatrix& M1, const TriMatrix& M2){
    TriMatrix M;
    M.mu = M1.mu;  M.nu = M2.nu; M.tu = 0;
    for(int i=0;i<M1.tu;i++){
        int c = M1.data[i].c;
        for(int j=M2.rpos[c];j<M2.rpos[c]+M2.rsum[c];j++){
            AddNode(M,M1.data[i].r,M2.data[j].c,M1.data[i].v * M2.data[j].v);
        }
    }
    return M;
}

int main(){
    // freopen("/config/workspace/answer/test.in","r",stdin);
    // freopen("/config/workspace/answer/test.out","w",stdout);
    TriMatrix M1, M2;
    InputMatrix(M1);
    InputMatrix(M2);
    CalcRPosMatrix(M1);
    CalcRPosMatrix(M2);
    // PrintMatrix(M1);
    // PrintMatrix(M2);

    TriMatrix M = Mul(M1,M2);
    CalcRPosMatrix(M);
    // PrintMatrix(M);
    PrintMatrixArray(M);
    return 0;
}

代码展示 

#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;

struct TriNode{
	int r,c,v;
};

void PrintTriNode(const TriNode& T){
	cout<<T.r<<" "<<T.c<<" "<<T.v<<endl;
}

struct TriMatrix{
	int mu,nu,tu;
	vector<TriNode> data;
	vector<int> rsum;
	vector<int> rpos;
};

void InputMatrix(TriMatrix& M){
	cin>>M.mu>>M.nu;
	M.tu=0;
	for(int i=0;i<M.mu;i++){
		for(int j=0;j<M.nu;j++){
			int t;cin>>t;
			if(t!=0){
				M.data.push_back({i,j,t});
				M.tu++;
			}
		}
	}
}

void CalcRPosMatrix(TriMatrix& M){
	for(int i=0;i<M.mu;i++){
		M.rsum.push_back(0);
	}
	for(int i=0;i<M.tu;i++){
		M.rsum[M.data[i].r]++;
	}//计算每行非零元个数
	M.rpos.push_back(0);
	for(int i=1;i<M.mu;i++){
		M.rpos.push_back(M.rsum[i-1]+M.rpos[i-1]);
	}//计算行向量
}

//调试用函数
void PrintMatrix(const TriMatrix& M){
	cout<<"========================================"<<endl;
	cout<<"mu="<<M.mu<<",nu="<<M.nu<<",tu="<<M.tu<<endl;
	for(int i=0;i<M.tu;i++){
		PrintTriNode(M.data[i]);
	}
	cout<<"rsum:";
	for(int i=0;i<M.mu;i++)  cout<<M.rsum[i]<<" ";
	cout<<endl;
	cout<<"rpos:";
	for(int i=0;i<M.mu;i++)  cout<<M.rpos[i]<<" ";
	cout<<endl;
	cout<<"========================================="<<endl;
}


void PrintMatrixArray(const TriMatrix& M){
	int array[M.mu][M.nu]={0};
	for(int i=0;i<M.mu;i++){
		for(int j=0;j<M.nu;j++){
			array[i][j]=0;
		}
	}
	for(int i=0;i<M.tu;i++){
		array[M.data[i].r][M.data[i].c]=M.data[i].v;
	}
	for(int i=0;i<M.mu;i++){
		for(int j=0;j<M.nu;j++){
			cout<<array[i][j]<<" ";
		}
		cout<<endl;
	}
}

void AddNode(TriMatrix& M,int r,int c,int v){
    //如果只想完成本题,以下几行足够了(三元组无序排列,但对之后的输出无影响)
	int flag=0;
	for(int i=0;i<M.tu;i++){
		if(M.data[i].r==r&&M.data[i].c==c){
			M.data[i].v+=v;
			flag=1;
		}
	}
	if(flag==0){
		M.data.push_back({r,c,v});
		M.tu++;
	}
    //如果追求完美,以下方法可以让结果三元组有序排列
    //对本题来说,可以没有,但是会使整个体系更完整
    /*
	if(M.tu==0){//第一个
		M.data.push_back({r,c,v});
		M.tu++;
	}
	else{
		int flag=0;
		for(int i=0;i<M.tu;i++){//遍历寻找是否有相同行列的值
			if(M.data[i].r==r&&M.data[i].c==c){
				M.data[i].v+=v;
				flag=1;
				break;
			}
		}
		if(flag)  return ;
		else{//寻找合适位置插入,以保证三元组的有序性
			for(int i=0;i<M.tu;i++){
				if(r>=M.data[i].r){
                    int loc=i;
                    while(c<M.data[i].c)  loc++;
					if(i==M.tu-1)
						M.data.push_back({r,c,v});
					else{
						vector<TriNode>::iterator it=M.data.begin();
						for(int j=0;j<loc+1;j++)  ++it;
						M.data.insert(it,{r,c,v});
					}
					M.tu++;
					break;
				}
			}
		}
	}
    */
}

//以下为附加代码
//三元组矩阵相乘
/*
TriMatrix Mul(const TriMatrix&M1,const TriMatrix& M2){
	TriMatrix M;
	M.mu=M1.mu;M.nu=M2.nu;M.tu=0;
	for(int i=0;i<M1.tu;i++){
		int c=M1.data[i].c;
		for(int j=M2.rpos[c];j<M2.rpos[c]+M2.rsum[c];j++){
			AddNode(M,M1.data[i].r,M2.data[j].c,M1.data[i].v*M2.data[j].v);
		}
	}
	return M;
}

int main(){
	freopen("/config/workspace/test/test","r",stdin);
	TriMatrix M1,M2;
	InputMatrix(M1);
	InputMatrix(M2);
	CalcRPosMatrix(M1);
	CalcRPosMatrix(M2);

	// PrintMatrix(M1);//调试用
	// PrintMatrix(M2);

	TriMatrix M=Mul(M1,M2);
	CalcRPosMatrix(M);
	PrintMatrixArray(M);
	return 0;
}
*/

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值