请编写并测试一个稀疏矩阵相乘的函数
matrix sparse_matrix_mul(const matrix&m1, constmatrix& m2)
其中matrix为一个描述稀疏矩阵的结构体:
struct matrix
{
float* _elements; //矩阵中所有元素的数组(按列优先的顺序)
int* _colheads; //每列的开始元素在_elements数组中的id
int* _colids; //_elements中每个元素在对应列中的行号
int _rows; //行数
int _cols; //列数
};
例如矩阵
0 1 0
2 4 5
3 0 0
对应结构中各数组为
_elements:{2,3,1,4,5}
_colheads:{0,2,4}
_colids:{1,2,0,1,1}.
请提交一个完整的可编译的程序和测试数据。
提示:请尽可能优化代码的时空间效率,并处理异常情况。
解决这道题:
我的思路是直接把上述结构体对应转换为矩阵相对应的位置(譬如,元素2对应矩阵[1][0]),然后直接运用矩阵公式计算,得到的结果保存为矩阵,然后再转换为该结构体,最后得出结果。其中应该可以实现的是:不需要把得到的结果保存为矩阵,而是可以直接计算然后转换到该结构体中,这样就不需要经过矩阵保存的步骤,节省了空间。
具体如何从结构体转换对应到矩阵的位置?这个就是该道题最核心的部分。
从第三个参数colids可以看到,每一个值对应一个元素,每个值代表的是行数。假如我要第一行的所有数组,那么就可以直接从colids数值看到,然后根据位置得到elements对应位置的值2,4,5是第一行,(从第0行开始计算)。
假如我要了解4元素的位置,那么可以通过colids得到对应的值,即是1,表示元素4的行数为1,列数暂时未知。
现在要考虑列数。
从第二个参数我们了解到:colheads是每列的开始元素在elements数组中的id,那么换句话说,在elements数组中,第0~1个是第一列,2~4是第二列,大于4的是第三列。那么就可以这样表示:
While(迭代)
If(i>=_colheads[j]&&i<_colheads[j+1]){
只要满足上述的的j就是列数,其中i表示所求元素值在elements的位置。譬如4在elements的位置为3,则i=3
}
最终的代码如下:
注意:输入的参数很多,为了方便测试,我把输入屏蔽掉,然后自己在代码里输入示例来测试。测试的数据不多,不保证算法的正确性,仅供参考。
#include<stdio.h>
#include<stdlib.h>
const int maxsize=1024;
int n1=5,n2=3,n3=5;
int nn1=5,nn2=3,nn3=5;
struct matrix
{
float* _elements; //矩阵中所有元素的数组(按列优先的顺序)
int* _colheads; //每列的开始元素在_m1._elements数组中的id
int* _colids; //_m1._elements中每个元素在对应列中的行号
int _rows; //行数
int _cols; //列数
};
void Init(matrix& m){
m._elements=(float*)malloc(sizeof(float*)*maxsize);
m._colheads=(int*)malloc(sizeof(int*)*maxsize);
m._colids=(int*)malloc(sizeof(int*)*maxsize);
}
matrix sparse_matrix_mul(const matrix& m1, const matrix& m2){
static float result[maxsize][maxsize];
matrix _result;
/*
_result._elements=(float*)malloc(sizeof(float*)*maxsize);
_result._colheads=(int*)malloc(sizeof(int*)*maxsize);
_result._colids=(int*)malloc(sizeof(int*)*maxsize);*/
Init(_result);
_result._rows=m1._rows;
_result._cols=m2._cols;
int i=0,j=0,k=0,l=0,m=0,n=0;
//矩阵计算
for(k=0;k<m1._rows;k++){
for(l=0;l<m2._cols;l++){
for(i=0;i<n3;i++){
if(m1._colids[i]== k ){//获取第k行的元素在m1._elements[]的位置
for(j=0;j<n2;j++){
if(i>=m1._colheads[j]&&i<m1._colheads[j+1]){//再获取第k行元素的列数,即a[k][j]==element[i]
for(m=0;m<nn3;m++){//以下则是获取a[j][l]的值
if(m2._colids[m]==j){//找到所有的行数为j的元素
for(n=0;n<nn2;n++){
if(m>=m2._colheads[n]&&m<m2._colheads[n+1]&&n==l){
result[k][l]+=m1._elements[i]*m2._elements[m];
break;
}
}
// break;
}
}
// break;
}
}
}
}
}
}
result[0][0]=1.0f;
k=0;
l=0;
bool isfirst=true;
for(i=0;i<_result._cols;i++){
for(j=0;j<_result._rows;j++){
if(result[j][i]!=0){
_result._elements[k]=result[j][i];
if(isfirst){
_result._colheads[l]=k;
l++;
isfirst=false;
}
_result._colids[k]=j;
k++;
}
}
isfirst=true;
}
//打印三元组
printf("类三元组形式:\n");
for(int z=0;z<k;z++)
printf("%.0f ",_result._elements[z]);
printf("\n");
for(int z=0;z<l;z++)
printf("%d ",_result._colheads[z]);
printf("\n");
for(int z=0;z<k;z++)
printf("%d ",_result._colids[z]);
printf("\n");
printf("矩阵形式\n");
for(i=0;i<m1._rows;i++){
for(j=0;j<m2._cols;j++){
printf("%.0f\t",result[i][j]);
}
printf("\n");
}
return _result;
}
void main(){
matrix m1,m2;
//申请空间
Init(m1);
Init(m2);
//例子:
/*
0 1 0 0 3 0
2 4 5 * 1 4 5
3 0 0 2 0 0
*/
m1._rows=3,m1._cols=3;
m2._rows=3,m2._cols=3;
m1._elements[0]=2;m1._elements[1]=3;m1._elements[2]=1;m1._elements[3]=4;m1._elements[4]=5;
m1._colheads[0]=0;m1._colheads[1]=2;m1._colheads[2]=4;
m1._colids[0]=1;m1._colids[1]=2;m1._colids[2]=0;m1._colids[3]=1;m1._colids[4]=1;
m2._elements[0]=1;m2._elements[1]=2;m2._elements[2]=3;m2._elements[3]=4;m2._elements[4]=5;
m2._colheads[0]=0;m2._colheads[1]=2;m2._colheads[2]=4;
m2._colids[0]=1;m2._colids[1]=2;m2._colids[2]=0;m2._colids[3]=1;m2._colids[4]=1;
//输入m1,m2矩阵
/*
scanf("%d%d%d",&n1,&n2,&n3);
for(int i=0;i<n1;i++)
scanf("%d",&m1._elements[i]);
for(int i=0;i<n2;i++)
scanf("%d",&m1._colheads[i]);
for(int i=0;i<n3;i++)
scanf("%d",&m1._colids[i]);
scanf("%d%d",&m1._rows,&m1._cols);
scanf("%d%d%d",&nn1,&nn2,&nn3);
for(int i=0;i<nn1;i++)
scanf("%d",&m2._elements[i]);
for(int i=0;i<nn2;i++)
scanf("%d",&m2._colheads[i]);
for(int i=0;i<nn3;i++)
scanf("%d",&m2._colids[i]);
scanf("%d%d",&m2._rows,&m2._cols);
*/
m1._colheads[n2]=999999;
m2._colheads[nn2]=999999;
matrix m=sparse_matrix_mul(m1,m2);//打印我放入该函数了
//以下对m的操作
system("pause");
}
运行结果: