稀疏矩阵相乘——三元组稀疏矩阵

请编写并测试一个稀疏矩阵相乘的函数

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");
}

运行结果:



  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值