题目描述
请使用带行向量的三元组法存储的稀疏矩阵,实现矩阵乘法。
本题为附加代码模式,以下代码会自动附加在提交的代码后面,请同学们注释之后提交
// 两个三元组法表示的矩阵相乘
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;
}
*/