稀疏矩阵课程设计
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
数据结构课程设计
设计说明书
稀疏矩阵相关操作的实现
学生姓名
学号
班级
成绩
指导教师
数学与计算机科学学院
2014年1月5日
课程设计任务书
2013—2014学年第1学期
专业:学号:姓名:
课程设计名称:课程设计Ⅰ
设计题目:稀疏矩阵相关操作的实现
完成期限:自年月日至年月日共周
设计内容:
若矩阵非零元较零元少,且分布没有一定规律,则称之为稀疏矩阵。
运用C、JA V A、VC++编程工具,编程实现稀疏矩阵的相关操作。
要求:
1)阐述设计思想,画出流程图;
2)主要功能:
(1)输入相关数据建立稀疏矩阵;
(2)实现稀疏矩阵转置;
(3)实现两个稀疏矩阵相乘。
3)从时间、空间对算法分析;
4)较好的界面设计;
5)编写课程设计报告。
以上要求中第一个阶段的任务完成后,先将设计说明书的草稿交指导老师面审,审查合格后方可进入后续阶段的工作。
设计工作结束后,经指导老师验收合格后将设计说明书打印装订,并进行答辩。
指导教师(签字):教研室负责人:
批准日期:年月日
课程设计评阅
摘要
本文以VC++作为软件开发环境,三元组表作为存储结构,设计与实现了稀疏矩阵运算器。
该计算器实现简单稀疏矩阵的乘法、转置、相乘等主要功能。
计算器。
界面清晰,操作简单,易于为用户所接受。
关键词:VC++;三元表;乘法;转置
目录
一、课题描述 (1)
二、问题描述 (2)
2.1 问题指出 (2)
2.2 问题需求 (2)
2.3 测试数据 (2)
2.4 问题阐述 (2)
三、算法描述 (3)
3.1 定义结构 (3)
3.2 实现功能 (3)
四、算法流程图 (5)
五、算法实现 (6)
5.1 菜单模块 (6)
5.2 建立矩阵模块 (7)
5.3 输出矩阵 (8)
5.4 转置矩阵 (9)
5.5 矩阵相乘 (9)
六、运行程序 (12)
6.1 菜单界面 (12)
6.2 建立矩阵 (12)
6.3 矩阵转置 (13)
6.4 矩阵相乘 (13)
七、时间及空间复杂度分析 (15)
八、总结 (16)
参考文献 (17)
一、课题描述
稀疏矩阵是指那些多数元素为零的矩阵。
利用“稀疏”特点进行存储和计算可以大大节省存储空间,提高计算效率。
实现一个能进行稀疏矩阵基本运算的运算器。
以“带行逻辑链接信息”的三元组顺序表表示稀疏矩阵,实现矩阵转置,两个矩阵相乘的运算。
稀疏矩阵的输入形式采用三元组表示,而运算结果的矩阵则以通常的矩阵形式列出。
首先应输入矩阵的行数和列数,并判别给出的两个矩阵的行、列数对于所要求作的运算是否相匹配。
可设矩阵的行数和列数均不超过20。
程序可以对三元组的输入顺序加以限制,例如,按行优先。
2.1 问题指出
稀疏矩阵是指那些多数元素为零的矩阵。
利用“稀疏”特点进行存储和计算可以大大节省存储空间,提高计算效率。
实现一个能进行稀疏矩阵基本运算的运算器。
2.2 问题需求
以三元组顺序表示稀疏矩阵,实现建立两个矩阵并实现转置和相乘的运算,稀疏矩阵的输入形式采用三元组表示,而运算结果的矩阵则以通常的阵列形式列出。
2.3 测试数据
4 -3 0 0 1 4 0 0 0
矩阵A 0 0 0 8 0 转置后为矩阵B -3 0 0 0
0 0 1 0 0 0 0 1 0
0 0 0 0 70 0 8 0 0
1 0 0 70
图2.1 矩阵转置
4 -3 0 0 1 3 0 0 0 -6 0
矩阵A 0 0 0 8 0 * 矩阵B 4 2 0 = 矩阵C 8 0 0
0 0 1 0 0 0 1 0 0 1 0
0 0 0 0 70 1 0 0 0 0 0
0 0 0
图2.2 矩阵相乘
2.4 问题阐述
(1)首先应输入矩阵的行数和列数,并判别给出的两个矩阵的行,列数对于所要求作的运算是否匹配,可设矩阵的行数和列数均不超过20。
(2)在用三元组表示稀疏矩阵时,转置或相乘所得结果矩阵应该另生成。
3.1 定义结构
typedef struct
{
int i,j; //非零元的行下标和列下标
ElemType e; //非零元的值
}Triple;
typedef struct{
Triple data[MAXSIZE+1];
int rpos[MAXRC+1]; //各行第一个非零元在三元组的位置表
int hs,ls,fls;
}TSMatrix,*Matrix;
抽象数据类型稀疏矩阵的定义如下:
ADT SparseMatrix{
数据对象:D={aij|i=1,2,3,…,m;j=1,2,…,n;
Aij(-ElemSet,m和n分别称为矩阵的行数和列数}
数据关系:R={Row,Col}
基本操作:
Create(&M);
操作结果:创建稀疏矩阵M。
Print_SMatrix(M);
初始条件:稀疏矩阵M存在。
操作结果:输出稀疏矩阵M。
Zhuanzhi(M,&T);
初始条件:稀疏矩阵M存在。
操作结果:求稀疏矩阵M的转置矩阵T。
xiangcheng(M,N,&Q);
初始条件:稀疏矩阵M的列数等于N的行数。
操作结果:求稀疏矩阵的积Q=M*N。
}ADT SpareMatrix
3.2 实现功能
(1) void Creat(TSMatrix &M) 创建稀疏矩阵
(2) int Xiangcheng(TSMatrix A,TSMatrix B,TSMatrix &Q) 稀疏矩阵相乘
(3) void Print_SMatrix(TSMatrix M) 输出矩阵
(4) void Zhuanzhi(TSMatrix *a,TSMatrix *b) 稀疏矩阵转置
四、算法流程图
图4.1 系统流程图
五、算法实现
5.1 菜单模块
打开程序开始运行时,出现控制菜单界面,选择对应的操作序号进行对应的操作,程序如下:
void main()
{
TSMatrix A,B,C,D,E;
TSMatrix *p=&A,*q=&B,*r=&D,*s=&E;
int flag,n;
while(1)
{
printf("\n");
printf("┏━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n");
printf("┃************* 稀疏矩阵的基本操作************┃\n"); printf("┃姓名:钟晓超学号:1118064073 ┃\n");
printf("┣━━━━━━━━━━━━━━━━━━━━━━━━━━┫\n");
printf("┃ 1、稀疏矩阵的创建┃\n");
printf("┃ 2、稀疏矩阵的转置┃\n");
printf("┃ 3、稀疏矩阵的乘法┃\n");
printf("┃ 4、退出该应用程序┃\n");
printf("┃***************欢迎使用********************** ┃\n");
printf("┗━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n");
printf("输入要进行的操作对应的编号:");
scanf("%d",&flag);
if(flag==4) break;
switch(flag)
{
case 1: printf("\t\t创建稀疏矩阵A\n");
Creat(A);
printf("输出矩阵A:\n"); Print_SMatrix(A);
printf("\t\t创建稀疏矩阵B\n");
Creat(B);
printf("输出矩阵B:\n"); Print_SMatrix(B);
break;
case 2: printf("输出A的转置矩阵D:\n");
Zhuanzhi(p,r);
Print_SMatrix(D);
printf("输出B的转置矩阵E:\n");
Zhuanzhi(q,s);
Print_SMatrix(E);
break;
case 3:
printf("输出矩阵A*矩阵B:\n");
n=Xiangcheng(A,B,C);
if(!n) printf("错误!行列不匹配\n");
else Print_SMatrix(C);
break;
default: printf("输入错误!\n");
} }
Destory_SMatrix(A);
Destory_SMatrix(B);
Destory_SMatrix(C);
getchar();getchar();
printf("\n\t\t\t ***程序已经退出***\n");
getchar();
}
5.2 建立矩阵模块
矩阵在建立之后才能够进行运算操作,建立矩阵A和矩阵B,调用函数Creat(M),首先根据所输入的矩阵的行数和列数,建立矩阵,其次再根据所输入矩阵的非零元个数做循环控制变量,按提示输入非零元所在的行和列以及非零元的值,最后将非零元的值保存在矩阵中的相应位置。
程序如下:
void Creat(TSMatrix &M) //创建稀疏矩阵
{
int i,k;
for(i=1;i<=MAXRC+1;i++)
M.rpos[i]=0;
printf("请输入矩阵的行数、列数和非零元个数(以空格隔开):");
scanf("%d %d %d",&M.hs,&M.ls,&M.fls);
for(i=1;i<=M.fls;i++)
{
printf("请用三元组形式输入矩阵的元素(行列非零元素):");
scanf("%d %d %d",&M.data[i].i,&M.data[i].j,&M.data[i].e);
}
for(i=1,k=1;i<=M.hs;i++)
{
M.rpos[i]=k;
while(M.data[k].i<=i && k<=M.fls)
k++;
}
}
5.3 输出矩阵
建立好矩阵以后,此函数能更直观的看到输入以及输出的矩阵,代码如下:void Print_SMatrix(TSMatrix M)//输出矩阵
{
int k,l,n;
Matrix p;
p=&M;
for(k=1,n=1;k<=p->hs;k++)
{
for(l=1;l<=p->ls;l++)
{
if(p->data[n].i==k && p->data[n].j==l)
{
printf("%5d",p->data[n].e);
n++;
}
else
printf("%5d",0);
}
printf("\n");
}
printf("\n");
}
5.4 转置矩阵
该函数实现的是矩阵A和矩阵B的转置操作,通过对矩阵的行和列进行调换,利用for()循环语句实现对矩阵A和矩阵B的转置,其代码如下:
void Zhuanzhi(TSMatrix *a,TSMatrix *b) //矩阵转置
{
int q,col,p;
b->hs=a->ls;
b->ls=a->hs;
b->fls=a->fls;
if(b->fls)
{
q=1;
for(col=1;col<=a->ls;col++)
for(p=1;p<=a->fls;p++)
if(a->data[p].j==col)
{
b->data[q].i=a->data[p].j;
b->data[q].j=a->data[p].i;
b->data[q].e=a->data[p].e;
++q;
}
}
}
5.5 矩阵相乘
实现两个矩阵之间的乘法运算,即A*B,如果矩阵A的列数和矩阵B的行数不相同,则无法进行乘法运算,系统会提示“错误,行列不匹配”,其代码如下:
int Xiangcheng(TSMatrix A,TSMatrix B,TSMatrix &Q)//矩阵相乘
{
int arow,brow,ccol,tp,p,q,t;
int ctemp[MAXRC+1];
if(A.ls!=B.hs)
return 0;
Q.hs=A.hs;Q.ls=B.ls;Q.fls=0;
if(A.fls*B.fls)
{
for(arow=1;arow<=A.hs;arow++)
{
for(ccol=1;ccol<=Q.ls;ccol++)
ctemp[ccol]=0;
Q.rpos[arow]=Q.fls+1;
if(arow<A.hs) tp=A.rpos[arow+1];
else tp=A.fls+1;
for(p=A.rpos[arow];p<tp;p++)
{
brow=A.data[p].j;
if(brow<B.hs)
t=B.rpos[brow+1];
else
t=B.fls+1;
for(q=B.rpos[brow];
q<t;q++)
{
ccol=B.data[q].j;
ctemp[ccol]+=A.data[p].e*B.data[q].e;
}
}
for(ccol=1;ccol<=Q.ls;ccol++)
{
if(ctemp[ccol]){
if(++Q.fls>MAXSIZE)
return 0;
Q.data[Q.fls].i=arow;
Q.data[Q.fls].j=ccol;
Q.data[Q.fls].e=ctemp[ccol];
}
}
}
}
return 1; }
六、运行程序
6.1 菜单界面
运行该运算系统,进入“菜单”选项,结果如图6.1所示:
图6.1“菜单”选项
6.2 建立矩阵
创建矩阵A和B,进入菜单选项之后,输入“1”,选择“稀疏矩阵的创建”,结果如图6.2和图6.3所示:
图6.2建立矩阵A
图6.3 建立矩阵B
6.3 矩阵转置
分别对A和B矩阵进行转置操作,进入菜单选项之后,输入“2”,选择“稀疏矩阵的转置”,结果如图6.4所示:
图6.4 转置矩阵A和矩阵B
6.4 矩阵相乘
实现A矩阵与B矩阵相乘,进入菜单选项之后,输入“3”,选择“稀疏矩阵的乘法”,结果如图6.5所示:
图6.5 矩阵A与矩阵B相乘
七、时间及空间复杂度分析
转置算法时间复杂度为O(M.ls*M.fls)。
矩阵乘法算法的时间复杂度:累加器ctemp初始化的时间复杂度为O(M.hs*N.ls),则所有的非零元的时间复杂度为O(M.fls*N.fls/N.hs),进行压缩矩阵的时间复杂度为O(M.hs*N.ls),总的时间复杂度就是O(M.hs*N.ls+M.fls*N.fls/N.hs)。
八、总结
通过对数据结构这门课的学习,我了解到:“数据结构”在计算机科学中是一门综合性的专业基础课。
而我们现在所学的数据结构是C语言版的,是建立在C语言基础之上的,若是C语言基础知识不牢固,要想学好数据结构这门课程是有一定的困难的。
所以在学习数据结构这门课程的时候,也顺便复习了C语言的相关内容,加深了我对C语言的理解和应用,并且也深深体会到了数据结构这门课程的重要性。
在本次课程设计过程中,我体会到自己所学的东西还是太少了,很多都不懂,也遇到了不少问题,使我发现了在学习过程中的不足。
这次课程设计,我应用了DOS界面来完成本次课程设计。
在代码设计时,也出现了一些基本的C语言语法错误,如函数的嵌套定义等,在老师和同学的帮助下都一一解决了,这也反映了我C语言基础知识的不扎实,以后应在学习过程中加强这方面的学习。
通过本次课程设计,我对数据结构这门课有了进一步的理解。
数据结构这门课最主要的内容在于算法思想,而程序编写次之。
在编写程序时,如果算法思想是正确的,那么这个程序就已经成功了一多半。
算法思想在数据结构中占有重要地位,如果说C语言是数据结构这座程序大厦的根基的话,那么算法思想就是构成大厦的一砖一瓦,再好的根基离了砖瓦也构不成大厦。
所以,要想学好数据结构这门课程,平时不只要加强程序的编写,更要多思考算法思想,加强对算法思想的锻炼和理解。
参考文献
[1] 严蔚敏,吴伟民.数据结构(C语言版)[M].北京:清华大学出版社,2002
[2] 李春葆.数据结构(C语言版)习题与解析[M].北京:清华大学出版社,2002
[3] 钱能.C++程序设计教程[M].北京:清华大学出版社,2003
17。