基于稀疏矩阵的加法的实现.docx
《基于稀疏矩阵的加法的实现.docx》由会员分享,可在线阅读,更多相关《基于稀疏矩阵的加法的实现.docx(15页珍藏版)》请在冰豆网上搜索。
基于稀疏矩阵的加法的实现
题目:
基于稀疏矩阵的加法的实现
初始条件:
理论:
学习了《数据结构》课程,掌握了基本的数据结构和常用的算法;
实践:
计算机技术系实验室提供计算机及软件开发环境。
要求完成的主要任务:
(包括课程设计工作量及其技术要求,以及说明书撰写等具体要求)
1、系统应具备的功能:
(1)设计稀疏矩阵的存储结构
(2)实现稀疏矩阵的加法
(3)输出结果
2、数据结构设计;
3、主要算法设计;
4、编程及上机实现;
5、撰写课程设计报告,包括:
(1)设计题目;
(2)摘要和关键字(中文和英文);
(3)正文,包括引言、需求分析、数据结构设计、算法设计、程序实现及测试、不足之处、设计体会等;
(4)结束语;
(5)参考文献。
时间安排:
2007年7月2日-7日(第18周)
7月2日查阅资料
7月3日系统设计,数据结构设计,算法设计
7月4日-5日编程并上机调试
7月6日撰写报告
7月7日验收程序,提交设计报告书。
指导教师签名:
2007年7月2日
系主任(或责任教师)签名:
2007年7月2日
稀疏矩阵相加的实现
摘要:
该程序实现了对简单矩阵的相加,但是仍存在一些问题未能解决。
设计该问题采用了C语言程序设计,简介而方便,它主要运用了建立函数,调用函数,建立递归函数等等方面来进行设计。
关键字:
稀疏矩阵,十字链表
1.引言
随着社会的不断进步以及数学和计算机科学的发展,矩阵的应用也越来广泛。
因而,如何更快的进行矩阵的各项运算也就成为了一项重要的问题,下面的这个程序简单的描述了稀疏矩阵的相加,有利于同学们对矩阵运算的了解。
2.需求分析
(1)构造稀疏矩阵并以三元组顺序表表示,矩阵的合法字符:
小写或大写字母、大括弧、顿号、分号,且稀疏矩阵用三元组来表示。
(2)演示程序是以系统为主、用户为辅进行执行的,稀疏矩阵的建立方式是用户事先在程序中建立,计算机系统自行输出显示的,然后分步自行显示每一个操作数据的结果。
3.数据结构设计
在这个程序中运用的存储结构是十字链表,对于十字链表的结构定义如下:
typedefstructOLNode
{
introw,col;/*非零元素的行和列下标*/
ElementTypevalue;
structOLNode*right;/*非零元素所在行表、列表的后继链域*/
structOLNode*down;
}OLNode;*OLink;
typedefstruct
{
OLink*row_head;/*行、列链表的头指针向量*/
OLink*col_head;
intm,n,len;/*稀疏矩阵的行数、列数、非零元素的个数*/
}CrossList;
4.算法设计
3.1算法的描述
在这个设计中我运用的是十字链表的存储结构,
3.2建立稀疏矩阵十字链表的算法
voidCreateCrossList(CrossList*M)
{
/*采用十字链表存储结构,创建稀疏矩阵M*/
scanf(&m,&n,&t);/*输入M的行数,列数和非零元素的个数*/
M->m=m;
M->n=n;
M->len=t;
if(!
(M->row_head=(OLink*)malloc((m+1)sizeof(OLink))))
exit(OVERFLOW);
if(!
(M->col_head=(OLink*)malloc((n+1)sizeof(OLink))))
exit(OVERFLOW);
M->row_head[]=M->col_head[]=NULL;/*初始化行、列头指针向量,各行、列链表为空的链表*/
for(scanf(&i,&j,&e);i!
=0;scanf(&i,&j,&e))
{
if(!
(p=(OLNode*)malloc(sizeof(OLNode))))
exit(OVERFLOW);
p->row=i;
p->col=j;
p->value=e;/*生成结点*/
if(M->row_head[i]==NULL)
M->row_head[i]=p;
else
3.2.1寻找行表中的插入位置的算法
for(q=M->row_head[i];q->right&&q->right->colright);/*空循环体*/
{p->right=q->right;
q->right=p;/*完成插入*/
}
if(M->col_head[j]==NULL)
M->col_head[j]=p;
else
3.2.2寻找列表中的插入位置的算法
for(q=M->col_head[j];q->down&&q->down->rowdown);/*空循环体*/
{p->down=q->down;
q->down=p;/*完成插入*/
}
3.3有关技术讨论
这个程序中运用了矩阵的相加运算:
创建十字链表,运用十字链表进行稀疏矩阵的加法运算。
5.程序实现
4.1部分模块的实现
4.1.1结构类型的定义及十字链表的稀疏矩阵创建的实现
/*Note:
YourchoiceisCIDE*/
#include
#include
#defineMAXMN20
typedefstructnode{
introw,col;
structnode*right,*down;
union{
structnode*next;
intval;
}member;
}matnode;/*定义结构类型*/
typedefmatnode*link;/*结构的指针*/
voidcrt_linkedmat(link*hm);/*创建十字链表的稀疏矩阵的函数*/
voiddis_linkedmat(linkhm);/*显示十字链表的稀疏矩阵的函数*/
voidinitiate(link*hc,intm,intn);
voidinsert(link*hc,linkp);/*将指针p插入到以*hc为头指针的十字链表中*/
linkadd(linkha,linkhb);
4.1.2十字链表的创建及初始化的实现
intmain()
{
linkha,hb,hc;
ha=NULL;
hb=NULL;
hc=NULL;/*初始化指针ha,hb,hc*/
crt_linkedmat(&ha);/*创建以ha为头指针的十字链表*/
dis_linkedmat(ha);/*将以ha为头指针的十字链表的稀疏矩阵显出来*/
getch();/*控制符*/
crt_linkedmat(&hb);/*同理创建以hb为头指针的十字链表*/
dis_linkedmat(hb);
getch();
hc=add(ha,hb);/*矩阵加法,结果返回到hc中*/
if(hc==NULL)
printf("Thesparsematrixescannotadd!
\n");
elsedis_linkedmat(hc);
getch();
return0;
}
4.1.3数据输入的实现
voidcrt_linkedmat(link*hm)
{
intm,n,tu,s,k;
inti,j,v;
linkcp[MAXMN];
linkp,q;
printf("Pleaseinputthematrix'srow,col,&tu:
\n");/*输入矩阵的行数,列数,和非零的值的个数*/
scanf("%d%d%d",&m,&n,&tu);
if(m>=n)s=m;elses=n;
p=(link)malloc(sizeof(matnode));
p->row=m;p->col=n;
*hm=p;cp[0]=p;
for(k=1;k
{
p=(link)malloc(sizeof(matnode));
p->row=0;p->col=0;
p->right=p;p->down=p;
cp[k]=p;
cp[k-1]->member.next=p;
}
cp[s]->member.next=(*hm);
for(k=1;k<=tu;k++)/*输入非零个数元素的值,以三元组的方式输入*/
{
printf("Pleaseinputtheelement'srow,col,val:
\n");
scanf("%d%d%d",&i,&j,&v);
p=(link)malloc(sizeof(matnode));
p->row=i;p->col=j;p->member.val=v;
q=cp[i];/*插入到行链中*/
while((q->right!
=cp[i])&&(q->right->colq=q->right;
p->right=q->right;
q->right=p;
q=cp[j];/*插入到列链中*/
while((q->down!
=cp[j])&&(q->down->row
q=q->down;
p->down=q->down;
q->down=p;
}
}
4.1.4十字链表的稀疏矩阵显示的实现
voiddis_linkedmat(linkhm)
{
intm,n,i;
linkcp[MAXMN];
linkp;
m=hm->row;
n=hm->col;
if(n>m)m=n;
cp[0]=hm;
for(i=1;i<=m;++i)
cp[i]=cp[i-1]->member.next;
for(m=1;m<=hm->row;++m)
{
for(n=1;n<=hm->col;++n)
{
p=cp[m]->right;
while((p!
=cp[m])&&(p->colp=p->right;
if((p!
=cp[m])&&(p->col==n))
printf("%d",p->member.val);
elseprintf("0");
}
printf("\n");
}
}
4.1.5初始化及创建循环链表的实现
初始化以*hc为头指针的十字链表,m为矩阵行数,n为矩阵的列数。
并初始化头节点指针,创建成头节点循环链表。
voidinitiate(link*hc,intm,intn)
{
linkcp[MAXMN],p;
ints,k;
p=(link)malloc(sizeof(matnode));
p->row=m;p->col=n;
*hc=p;cp[0]=p;
s=m>n?
m:
n;
for(k=1;k<=s;++k)
{
p=(link)malloc(sizeof(matnode));
p->row=0;p->col=0;
p->right=p;p->down=p;
cp[k]=p;
cp[k-1]->member.next=p;
}
cp[s]->member.next=(*hc);
}
4.1.6指针插入十字链表的实现
将指针p插入到以*hc为头指针的十字链表中。
voidinsert(link*hc,linkp)
{
intm,n,i;
linkcp[MAXMN],q;
m=(*hc)->row;n=(*hc)->col;
if(n>m)m=n;
cp[0]=(*hc);
for(i=1;i<=m;++i)
cp[i]=cp[i-1]->member.next;
m=p->row;n=p->col;
q=cp[m];/*插入到行链中*/
while((q->right!
=cp[m])&&(q->right->colq=q->right;
p->right=q->right;q->right=p;
q=cp[n];/*插入到列链中*/
while((q->down!
=cp[n])&&(q->down->rowdown;
p->down=q->down;q->down=p;
}
4.1.7矩阵加法的实现
矩阵的加法函数,返回结果的头指针hc。
linkadd(linkha,linkhb)
{
linkhc,ca,cb,pa,pb,p;
intm,n,val,flag;
hc=NULL;
if((ha->row!
=hb->row)||(ha->col!
=hb->col))/*判断是否具备相加的条件*/
returnhc;/*不能相加返回NULL*/
else{
m=ha->row;n=ha->col;/*行值m和列值n*/
initiate(&hc,m,n);/*初始化hc*/
ca=ha->member.next;cb=hb->member.next;/*ca和cb分别为第一个头节点,即是第一行链的头节点*/
while((ca!
=ha)&&(cb!
=hb)){/*当行链值都不等于头指针ha和hb*/
pa=ca->right;pb=cb->right;/*分别指向行链中的第一个元素节点*/
while((pa!
=ca)&&(pb!
=cb))
if(pa->colcol)/*比较列值,如果pa的列值小的话,标志为1*/
flag=1;
if(pa->col>pb->col)/*同理,pb的列值小的话,标志为2*/
flag=2;
if(pa->col==pb->col)/*相等时,标志为3*/
flag=3;
switch(flag){
case1:
insert(&hc,pa);/*为1时,插入pa*/
pa=pa->right;/*使pa向后移一个节点*/
break;
case2:
insert(&hc,pb);/*为2时,插入pb*/
pb=pb->right;/*使pb向后移一个节点*/
break;
case3:
val=pa->member.val+pb->member.val;/*为3时,值相加*/
if(val){
/*若不为0,则申请一个节点,并将这节点插入到hc*/
p=(link)malloc(sizeof(matnode));
p->row=pa->row;p->col=pa->col;
p->member.val=val;
insert(&hc,p);
}
break;
}
}
while((pa!
=ca)&&(pb==cb)){/*pa还没回到头节点,pb已是头节点时*/
insert(&hc,pa);
pa=pa->right;
}
while((pa==ca)&&(pb!
=cb)){/*pa回到头节点,pb还没回到*/
insert(&hc,pb);
pb=pb->right;
}
ca=ca->member.next;cb=cb->member.next;/*继续处理下一行*/
}
returnhc;
}
}
4.2运行结果
4.2.1运行界面
4.2.2输入矩阵的行列数以及非零元素的个数
4.2.3输入具体数据及输出
6.设计体会
做程序是一个比较累的工作,特别是当遇到困难时,程序通不过时,真的很令人沮丧。
但是改正一个错误时,那种喜悦心情也很令人期盼,这种心情堪比久旱见甘霖的喜悦。
就是因为有这种令人身心愉悦的可能,我才得以能够整晚不睡来改程序中的不足之处。
编程中有苦有乐,其中的苦乐只有亲身经历才能体会到。
要想做出好的程序,必须做好忍受其间痛苦的准备。
通过这个星期的课程设计,我的收获还是不少。
我的c语言水平有了比较大的提高,其中c语言关于指针,链表的操作理解的比以前深刻不少。
另外是数据结构方面的提高,对存储结构,及各种查找排序方面也有不少的提高。
虽然我做的程序里还有写问题,做的不够深入,但独立完成一个比较大一点的程序的经历也是很宝贵的。
7.结束语
C语言功能强,使用灵活,可移植性好,目标程序质量好,它既有高级语言的优点,又具有低级语言的许多特点,既可以用来编写系统软件,又可以编写应用软件,由于c语言语法限制不严格,程序设计自由度大,在使用时会出现一些”副作用”,所以学好c语言最好有过学习一门其他语言.
在编程过程中善于发现程序中的错误,并且能很快地排除这些错误,使程序能正确运行。
经验丰富的人,当编译时出现“出错信息”时,能很快地判断出错误所在,并改正之。
而缺乏经验的人即使在明确的出错提示下也往往找不出错误而求救于别人。
调试程序的经验固然可以借鉴他人的现成经验,但更重要的是通过自己的直接实践来累积,而且有些经验是只能“会意”难以“言传”。
因此,在实验时千万不要在程序通过后就认为万事大吉、完成任务了,而应当在已通过的程序基础上作一些改动(例如修改一些参数、增加程序一些功能、改变输入数据的方法等),再进行编译、连接和运行。
参考文献
[1]严蔚敏,吴伟民.《数据结构》,清华大学出版社,2001年1月
[2]张颖江,胡燕.《C语言程序设计》,科学出版社,1998年7月
[3]谭浩强.《C程序设计》,清华大学出版社,1999年12月