课程设计任务书学生姓名:专业班级:指导教师:夏红霞工作单位:计算机科学与技术学院题目: 稀疏矩阵乘法的运算课程设计要求:1、熟练掌握基本的数据结构;2、熟练掌握各种算法;3、运用高级语言编写质量高、风格好的应用程序。
课程设计任务:1、系统应具备的功能:(1)设计稀疏矩阵的存储结构(2)建立稀疏矩阵(3)实现稀疏矩阵的乘法2、数据结构设计;3、主要算法设计;4、编程及上机实现;5、撰写课程设计报告,包括:(1)设计题目;(2)摘要和关键字;(3)正文,包括引言、需求分析、数据结构设计、算法设计、程序实现及测试、不足之处、设计体会等;(4)结束语;(5)参考文献。
时间安排:2010年7月5日-9日(第19周)7月5日查阅资料7月6日系统设计,数据结构设计,算法设计7月7日 -8日编程并上机调试7月9日撰写报告7月10日验收程序,提交设计报告书。
指导教师签名: 2010年7月4日系主任(或责任教师)签名: 2010年7月4日目录1.摘要 (1)2.关键字 (1)3.引言 (1)4. 问题描述 (1)5. 系统设计 (1)6. 数据结构 (3)7. 算法描述 (3)8. 测试结果与分析 (4)9. 源代码 (12)10. 总结 (29)11.参考文献 (29)稀疏矩阵乘法的运算1.摘要:在一些数值计算中,一些二维矩阵的乘法运算很常见,我们经常采用线性代数中的知识进行运算,然而对一些含有非零元很少的二维矩阵也采用相同的方法时,就会发现那样的方法不仅需要很多的空间来存储0,造成空间复杂度比较大,而且算法的时间复杂度也较大。
因此需要采取其他的方法来解决这个问题,由于0在乘法中其结果总是0,所以可以考虑采用三元组的方式去存储稀疏矩阵中的非零元,这样在计算过程中不仅需要的内存空间减少了,而且运算的速率也提高了。
2.关键字:稀疏矩阵乘法二维矩阵算法复杂度3.引言:随着科学技术的发展,人们对矩阵的运算的几率越来越大,特别是高新科技研究中对矩阵的运算更是常见。
但是如何高效的并占内存少的进行矩阵运算就是一个急需解决的问题。
本文主要对稀疏矩阵的存储以及稀疏矩阵的乘法运算进行了研究和探讨。
4.问题描述:在一些数值计算中,一些二维矩阵的乘法运算很常见,我们经常采用线性代数中的知识进行运算,然而对一些含有非零元很少的二维矩阵也采用相同的方法时,就会发现那样的方法不仅需要很多的空间来存储0,造成空间复杂度比较大,而且算法的时间复杂度也较大。
为了减少空间和时间复杂度,可以根据给定的二维数组的数据设计稀疏矩阵的存储结构,然后根据设计的稀疏矩阵存储结构建立一个稀疏矩阵,最后获得两个二维数组得到他们各自的稀疏矩阵,计算这两个稀疏矩阵的乘积。
5.系统设计:5.1 设计目标:通过一定的数据结构,存储含有少量数据的矩阵,把他们存入一个稀疏矩阵中,然后实现稀疏矩阵的乘法运算。
[基本要求]设计稀疏矩阵的存储结构;建立稀疏矩阵;实现稀疏矩阵的乘法5.2 系统实现的操作和功能:5.2.1初始化:初始化一些数据5.2.2获得数据:根据客户的要求可以采用人工输入和从文件中读取数据两种方式获得二维矩阵的中的数据。
然后根据相应的数据建立稀疏矩阵。
5.2.3检查数据的合法性:当这两个二维矩阵不满足矩阵相乘的条件时,系统将报错,并退出系统。
5.2.4稀疏矩阵的乘法:当两个二维矩阵合法时将对其进行乘法运算,然后将结果输出并按用户的要求保存到相应的文件中。
5.3设计思想:在操作的过程中采用三元组建立稀疏矩阵。
用户可以通过输入数据或者文件名以后,系统会自动建立一个三元组的稀疏矩阵,然后对其进行乘法运算。
在里面主要包含两个函数文件:获得数据并建立稀疏矩阵,对稀疏矩阵进行合法性的检查并进行乘法运算。
5.4系统模块划分:6.数据结构:采用结构体存储每行每列的元素:typedef struct DataNode {int row ;//存储所在二维矩阵的行数 int col ;//存储所在二维矩阵的列数稀疏矩阵乘法的运算获得数据并建立稀疏矩阵检查矩阵合法性并进行乘法运算输出结果并存到指定文件中数据初始化ElemType data;//存储row行col列的元素的值}DataNode;采用结构体存储稀疏二维数组:typedef struct SparseMatrix{DataType *matrix;//用数组存储非零元int row;//二维数组的行数int col;//二维数组的列数int *rpos;//每行第一个非零元在matrix中的位置int num;//非零元的个数int con;//指定常数};注:在第二个结构体中num和con这两个变量,在本此系统中con默认为0,num的功能是检验数据是否完整。
当二维数组中出现很多非零元素值一样的时候,也可以采用三元组的方法存储,只要让con等于那个非零元素值即可。
7.算法描述:本系统的主要算法为稀疏矩阵的乘法运算。
算法如下:Q初始化;if (Q是非零矩阵){//逐行求积for(arow=1;arow<=M.row;++arow){//处理M的每一行ctemp[]=0;//累加器清零计算Q中第arow行的积并存入ctemp[]中;将ctemp[]中的非零元压缩存储到Q.matrix中;}}8.测试结果与分析:测试1:两个文件数据完全正确Input the method of getting data(1 is from file,2 is from inputting):1 Input two names of the data file:data1.txt data2.txtRead the first file successfully!Read the second file successfully!The first matrix is:1 1 31 4 52 2 -13 1 2The second matrix is:1 2 22 1 13 1 -23 2 4The result is:3 0 3 21 2 62 1 -13 2 4Input one name of the data file:data5.txt测试2:一个文件数据完全正确,另一个文件数据不正确Input the method of getting data(1 is from file,2 is from inputting):1 Input two names of the data file:data1.txt data4.txtRead the first file successfully!The data is wrong!The first data is wrong!Please check it carefully,then input it again:1 2 2The data is wrong!The 4th data is wrong!Please check it carefully,then input it again:3 2 4Read the second file successfully!The first matrix is:1 1 31 4 52 2 -13 1 2The second matrix is:1 2 22 1 13 1 -23 2 4The result is:3 0 3 21 2 62 1 -13 2 4Input one name of the data file:data6.txt测试3:两个数据文件都错误Input the method of getting data(1 is from file,2 is from inputting):1 Input two names of the data file:data3.txt data4.txtThe data is wrong!The second data is wrong!Please check it carefully,then input it again:The data is wrong!The 4th data is wrong!Please check it carefully,then input it again: 3 1 2Read the first file successfully!The data is wrong!The first data is wrong!Please check it carefully,then input it again: 1 2 2The data is wrong!The 4th data is wrong!Please check it carefully,then input it again: 3 2 4Read the second file successfully!The first matrix is:1 1 31 4 52 2 -13 1 2The second matrix is:1 2 22 1 13 1 -23 2 4The result is:3 0 3 21 2 62 1 -1Input one name of the data file:data7.txt测试4:不符合矩阵乘法运算条件Input the method of getting data(1 is from file,2 is from inputting):1Input two names of the data file:data.txt data1.txtRead the first file successfully!Read the second file successfully!The first matrix is:1 2 121 3 93 1 -33 6 144 3 245 2 186 1 156 4 -7The second matrix is:1 1 31 4 52 2 -13 1 2The matrix multiply is illegal!测试5:输入数据完全正确Input the method of getting data(1 is from file,2 is from inputting):2Input the first matrix:With the order of a specified number of constant,specified constant and rows and columns number:4 0 3 4Enter each element of a two-dimensional arrays in the number of rows and columns and the location of the element value:1 1 31 4 52 2 -13 1 2Input the second matrix:With the order of a specified number of constant,specified constant and rows and columns number:4 0 4 2Enter each element of a two-dimensional arrays in the number of rows and columns and the location of the element value:1 2 22 1 13 1 -23 2 4The first matrix is:1 1 31 4 52 2 -13 1 2The second matrix is:1 2 22 1 13 1 -23 2 4The result is:3 0 3 22 1 -13 2 4Input one name of the data file:data8.txt测试6:输入数据时有错误Input the method of getting data(1 is from file,2 is from inputting):2Input the first matrix:With the order of a specified number of constant,specified constant and rows and columns number:4 0 3 4Enter each element of a two-dimensional arrays in the number of rows and columns and the location of the element value:1 1 31 4 52 2 -13 1 2Input the second matrix:With the order of a specified number of constant,specified constant and rows and columns number:4 0 4 2Enter each element of a two-dimensional arrays in the number of rows and columns and the location of the element value:1 2 22 1 13 1 -23 3 4The data is wrong!Input again:3 2 4The first matrix is:1 4 52 2 -13 1 2The second matrix is:1 2 22 1 13 1 -23 2 4The result is:3 0 3 21 2 62 1 -13 2 4Input one name of the data file:data9.txt测试7:输入数据不满足矩阵相乘的条件Input the method of getting data(1 is from file,2 is from inputting):2Input the first matrix:With the order of a specified number of constant,specified constant and rows and columns number:4 0 3 4Enter each element of a two-dimensional arrays in the number of rows and columns and the location of the element value:1 1 31 4 52 2 -13 1 2Input the second matrix:With the order of a specified number of constant,specified constant and rows and columns number:8 0 6 7Enter each element of a two-dimensional arrays in the number of rows and columns and the location of the element value:1 2 121 3 93 1 -33 6 144 3 245 2 186 1 156 4 -7The first matrix is:1 1 31 4 52 2 -13 1 2The second matrix is:1 2 121 3 93 1 -33 6 144 3 245 2 186 1 156 4 -7The matrix multiply is illegal!9.源代码:----------------------------Makefile------------------------------- CC=gccCLFAGS=-g -Wall -O2 -lmOBJECTS=main.o getdata.o init.o matrixmulti.o print.o main:$(OBJECTS)$(CC) $(CLFAGS) -o $@ $^.c.o:$(CC) -c $<.PHONY:cleanclean:rm -f $(OBJECTS) main-------------------------------main.c------------------------------- /*---------------------------基本信息------------------------------- 作者:方金卫日期:2010年7月8日系统名称:稀疏矩阵乘法系统功能:稀疏矩阵的乘法-------------------------------------------------------------------*/ #include<stdio.h>#include"data.h"int main(void){SparseMatrix sparsematrix1;SparseMatrix sparsematrix2;SparseMatrix sparsematrix3;char filename1[32];char filename2[32];char filename3[32];int tag;int sign;printf("Input the method of getting data(1 is from file,2 is from inputting):"); scanf("%d",&tag);InitSparseMatrix(&sparsematrix1);InitSparseMatrix(&sparsematrix2);/*初始化*//*获取数据*/if(tag==1){printf("Input two names of the data file:");scanf("%s %s",filename1,filename2);sign=GetData(&sparsematrix1,filename1);if(sign==1)printf("Read the first file successfully!\n");if(sign==-1)return 0;sign=GetData(&sparsematrix2,filename2);if(sign==1)printf("Read the second file successfully!\n");if(sign==-1)return 0;if(tag==2){printf("Input the first matrix:\n");InputData(&sparsematrix1);printf("Input the second matrix:\n");InputData(&sparsematrix2);}/*输出稀疏矩阵*/printf("The first matrix is:\n");PrintMatrix(sparsematrix1);printf("The second matrix is:\n");PrintMatrix(sparsematrix1);sparsematrix3=MatrixMulti(sparsematrix1,sparsematrix2);/*稀疏矩阵的乘法运算*//*输出结果*/printf("The result is:\n");printf("%d %d %d %d\n",sparsematrix3.num,sparsematrix3.con,sparsematrix3.row,sp arsematrix3.col);PrintMatrix(sparsematrix3);/*输出到指定的文件中*/printf("Input one name of the data file:");scanf("%s",filename3);PrintToFile(sparsematrix3,filename3);return 1;}--------------------------------data.h------------------------------#ifndef DATA_H_#define DATA_H_#include<stdio.h>#include<stdlib.h>#define INT#ifdef FLOATtypedef float DataType;#endif#ifdef INTtypedef int DataType;#endif#define MAXSIZE 30#define INITMAX 65535typedef int Status;/*-----------------定义数据结构-----------------*//*定义数据节点:每个节点存放所在的行数与列数,以及该处的值*/ typedef struct DataNode{int row,col;/*该元素所在的行数和列数*/DataType data;}DataNode;/*数组的行列数*/typedef struct SparseMatrix{int num;/*非指定元素的个数*/int con;/*指定常数*/int row,col;/*矩阵的行数和列数*/DataNode *matrix;int *rpos;/*各行第一个非指定元素的位置表,若不含某行时其值为-1*/}SparseMatrix;/*-----------------一些基本操作-----------------*//*In the getdata.c file*/Status InputData(SparseMatrix *sparsematrix);/*人工输入数据*/Status GetData(SparseMatrix *sparsematrix,char filename[]);/*从指定的文件中获得数据*//*In the init.c file*/Status InitSparseMatrix(SparseMatrix *sparsematrix);/*初始化稀疏矩阵的数据*//*In the matrixmulti.c file*/SparseMatrix MatrixMulti(SparseMatrix sparsematrix1,SparseMatrix sparsematrix2);/*稀疏矩阵相乘*//*In the print.c file*/void PrintMatrix(SparseMatrix sparsematrix);/*输出系数矩阵里的值*/void PrintToFile(SparseMatrix sparsematrix,char filename[]);/*将矩阵输入指定的文件中*/#endif--------------------------------init.c------------------------------#include"data.h"/*初始化数据*/Status InitSparseMatrix(SparseMatrix *sparsematrix){int i;(*sparsematrix).num=0;(*sparsematrix).con=0;(*sparsematrix).row=0;(*sparsematrix).col=0;(*sparsematrix).matrix=(DataNode*)malloc(sizeof(DataNode));if(!(*sparsematrix).matrix){printf("Memory allocation failed in init.c!\n");exit(1);}(*sparsematrix).matrix=NULL;(*sparsematrix).rpos=(int *)malloc(sizeof(int));if(!(*sparsematrix).rpos){printf("Memory allocation failed in init.c!\n");exit(1);}(*sparsematrix).rpos=NULL;return 1;}-----------------------------getdata.c-------------------------------#include"data.h"/*-----------------------检验数据的合法性--------------------------*/Status IsRight(SparseMatrix sparsematrix,int i){if(sparsematrix.matrix[i].row>sparsematrix.row||sparsematrix.matrix[i].col>sparsemat rix.col){printf("The data is wrong!\n");return 0;}return 1;}/*---------------------从文件中读取数据-------------------------*/Status GetData(SparseMatrix *sparsematrix,char filename[]){FILE *fp;int i;int *count;/*辅助确定每行第一个元素的位置*/InitSparseMatrix(sparsematrix);if((fp=fopen(filename,"r+"))==NULL){printf("Can't open this file!\n");exit(1);}/*分别获得二维矩阵非指定常数的个数,指定常数,以及它的行数和列数*/ fscanf(fp,"%d%d%d%d",&(*sparsematrix).num,&(*sparsematrix).con,&(*sparsematr ix).row,&(*sparsematrix).col);(*sparsematrix).matrix=(DataNode*)malloc(((*sparsematrix).num+1)*sizeof(DataNo de));if(!(*sparsematrix).matrix){printf("Memory allocation failed in getdata.c!\n");exit(1);}(*sparsematrix).rpos=(int *)malloc(((*sparsematrix).row+1)*sizeof(int));if(!(*sparsematrix).rpos){printf("Memory allocation failed in getdata.c!\n");exit(1);}count=(int *)malloc(((*sparsematrix).row+1)*sizeof(int));if(!count){printf("Memory allocation failed in getdata.c!\n");exit(1);}for(i=0;i<=(*sparsematrix).row;++i)/*初始化数组*/{(*sparsematrix).rpos[i]=0;count[i]=0;}/*0号单元都不用*/for(i=1;i<=(*sparsematrix).num&&!feof(fp);++i){fscanf(fp,"%d",&(*sparsematrix).matrix[i].row);fscanf(fp,"%d",&(*sparsematrix).matrix[i].col);++count[(*sparsematrix).matrix[i].row];/*统计每行非零元素个数*/ #ifdef FLOATfscanf(fp,"%f",&(*sparsematrix).matrix[i].data);#endif#ifdef INTfscanf(fp,"%d",&(*sparsematrix).matrix[i].data);#endifwhile(IsRight(*sparsematrix,i)==0)/*检验数据的合法性*/{if(i==1)printf("The first data is wrong!\n");else if(i==2)printf("The second data is wrong!\n");else if(i==3)printf("The third data is wrong!\n");elseprintf("The %dth data is wrong!\n",i);printf("Please check it carefully,then input it again:\n");--count[(*sparsematrix).matrix[i].row];/*第row的非指定常数的个数减一*/scanf("%d",&(*sparsematrix).matrix[i].row);scanf("%d",&(*sparsematrix).matrix[i].col);++count[(*sparsematrix).matrix[i].row];/*统计每行非零元素个数*/ #ifdef FLOATscanf("%f",&(*sparsematrix).matrix[i].data);#endif#ifdef INTscanf("%d",&(*sparsematrix).matrix[i].data);#endif}}if(i!=(*sparsematrix).num+1){printf("Get data wrong!\n");return -1;}/*确定每行第一个非指定常数在rpos数组的位置*/for(i=1;i<=(*sparsematrix).row;++i){(*sparsematrix).rpos[i]=count[i-1]+1;count[i]+=count[i-1];}fclose(fp);return 1;}/*----------------------通过终端人工输入数据---------------------*/Status InputData(SparseMatrix *sparsematrix){int i;int *count;InitSparseMatrix(sparsematrix);printf("With the order of a specified number of constant,specified constant and rows and columns number:\n");scanf("%d %d %d %d",&(*sparsematrix).num,&(*sparsematrix).con,&(*sparsematri x).row,&(*sparsematrix).col);(*sparsematrix).matrix=(DataNode*)malloc(((*sparsematrix).num+1)*sizeof(DataNo de));if(!(*sparsematrix).matrix){printf("Memory allocation failed in getdata.c!\n");exit(1);}(*sparsematrix).rpos=(int *)malloc(((*sparsematrix).row+1)*sizeof(int));if(!(*sparsematrix).rpos){printf("Memory allocation failed in getdata.c!\n");exit(1);}count=(int *)malloc(((*sparsematrix).row+1)*sizeof(int));if(!count){printf("Memory allocation failed in getdata.c!\n");exit(1);}for(i=0;i<=(*sparsematrix).row;++i){(*sparsematrix).rpos[i]=0;count[i]=0;}printf("Enter each element of a two-dimensional arrays in the number of rows and columns and the location of the element value:\n");for(i=1;i<=(*sparsematrix).num;++i){scanf("%d",&(*sparsematrix).matrix[i].row);scanf("%d",&(*sparsematrix).matrix[i].col);++count[(*sparsematrix).matrix[i].row];/*统计每行非零元素个数*/#ifdef FLOATscanf("%f",&(*sparsematrix).matrix[i].data);#endif#ifdef INTscanf("%d",&(*sparsematrix).matrix[i].data);#endifif(IsRight(*sparsematrix,i)==0)/*检验数据的合法性*/{printf("Input again:");--i;}}/*确定每行第一个非指定常数在rpos数组的位置*/for(i=1;i<=(*sparsematrix).row;++i){(*sparsematrix).rpos[i]=count[i-1]+1;count[i]+=count[i-1];}return 1;}---------------------------matrixmulti.c-----------------------------#include"data.h"/*两个稀疏矩阵相乘*/SparseMatrix MatrixMulti(SparseMatrix sparsematrix1,SparseMatrix sparsematrix2) {SparseMatrix sparsematrix3;int arow,ccol,brow,temp,tp,temp1,temp2;DataType ctemp[MAXSIZE+1]={};int i;if(sparsematrix1.col!=sparsematrix2.row){printf("The matrix multiply is illegal!\n");exit(1);}InitSparseMatrix(&sparsematrix3);/*结果矩阵的初始化*/sparsematrix3.row=sparsematrix1.row;sparsematrix3.col=sparsematrix2.col;sparsematrix3.num=0;/*为数组rpos分配空间*/sparsematrix3.rpos=(int *)malloc(sparsematrix3.row*sizeof(int));if(!sparsematrix3.rpos){printf("Memory allocation failed!\n");exit(1) ;}sparsematrix3.matrix=(DataNode*)malloc(sparsematrix3.row*sparsematrix3.col*sizeof(DataNode));if(!sparsematrix3.matrix){printf("Memory allocation failed!\n");exit(1);}if(!sparsematrix3.rpos){printf("Memory allocation failed!\n");exit(1);}if(sparsematrix3.col>MAXSIZE){printf("The MAXSIZE is defined smaller,please define it again!\n");exit(1);}if(sparsematrix1.num*sparsematrix2.num!=0)/*非零矩阵*/ {for(arow=1;arow<=sparsematrix1.row;++arow)/*处理第一个矩阵的每一行*/{for(i=0;i<=MAXSIZE;++i) /*当前行各元素累加器清零*/ctemp[i]=0;sparsematrix3.rpos[arow]=sparsematrix3.num+1;/*统计每行第一个非指定元素的位置*/if(arow<sparsematrix1.row) tp=sparsematrix1.rpos[arow+1];else tp=sparsematrix1.num+1;for(temp=sparsematrix1.rpos[arow];temp<tp;++temp){/*对当前行中每一个非零元*/brow=sparsematrix1.matrix[temp].col;/*找到对应元在第二个矩阵对应的行号*/if(brow<sparsematrix2.row)temp1=sparsematrix2.rpos[brow+1];else temp1=sparsematrix2.num+1;for(temp2=sparsematrix2.rpos[brow];temp2<temp1;++temp2){ccol=sparsematrix2.matrix[temp2].col;/*乘积元素结果矩阵中的列号*/ctemp[ccol]+=sparsematrix1.matrix[temp].data*sparsematrix2.matrix[temp2].data;}}for(ccol=1;ccol<=sparsematrix3.col;++ccol)/*压缩存储该行所有非指定常数*/if(ctemp[ccol]){if(++sparsematrix3.num>MAXSIZE) return ;sparsematrix3.matrix[sparsematrix3.num].row=arow;sparsematrix3.matrix[sparsematrix3.num].col=ccol;sparsematrix3.matrix[sparsematrix3.num].data=ctemp[ccol];}}}return sparsematrix3;}-----------------------------print.c-----------------------------#include"data.h"/*输出稀疏矩阵*/void PrintMatrix(SparseMatrix sparsematrix){int i;if(sparsematrix.num==0){printf("The sparse matrix is empty!\n");return ;}for(i=1;i<=sparsematrix.num;++i){#ifdef FLOATprintf("%d %d %f\n",sparsematrix.matrix[i].row,sparsematrix.matrix[i].col,sparsematr ix.matrix[i].data);#endif#ifdef INTprintf("%d %d %d\n",sparsematrix.matrix[i].row,sparsematrix.matrix[i].col,sparsemat rix.matrix[i].data);#endif}}/*输出稀疏矩阵到指定的文件里*/void PrintToFile(SparseMatrix sparsematrix,char filename[]){FILE *fp;int i;if((fp=fopen(filename,"w"))==NULL){printf("Open this file errror!\n");return ;}fprintf(fp,"%d %d %d %d\n",sparsematrix.num,sparsematrix.con,sparsematrix.row,sp arsematrix.col);for(i=1;i<=sparsematrix.num;++i){fprintf(fp,"%d ",sparsematrix.matrix[i].row);fprintf(fp,"%d ",sparsematrix.matrix[i].col);fprintf(fp,"%d",sparsematrix.matrix[i].data);fprintf(fp,"\n");}fclose(fp);}10.总结:这个系统的主要功能是计算两个稀疏矩阵的乘法运算,本系统可以采用人工输入和读取文件获得数据,在运算的过程中对数据的合法性进行了检查,以及两个矩阵是否满足进行乘法运算的条件,这保证了系统的健壮性。