课程设计 稀疏矩阵应用

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

数学与计算机学院
课程设计说明书
课程名称: 数据结构课程设计
课程代码: 8404181
题目: 稀疏矩阵应用
年级/专业/班:
学生姓名:
学号:
开始时间:2011 年06 月13日完成时间:2011 年06月21 日课程设计成绩:
学习态度及平时成绩(30)技术水平与实际
能力(20)
创新(5)说明书撰写质量(45)
总分
(100)
指导教师签名:年月日
目录
1 引言 (1)
1.1问题的提出 (1)
1.2国内外研究的现状 (1)
1.3任务与分析 (1)
2 程序的主要功能 (1)
2.1三元组的转置 (1)
2.2三元组的加法 (1)
2.3三元组的减法 (1)
2.4三元组的乘法 (2)
2.5十字链表的转置 (2)
2.6十字链表的加法 (2)
2.7十字链表的减法 (2)
2.8十字链表的乘法 (2)
3程序运行平台 (3)
4总体设计 (3)
5程序类的说明 (4)
6 模块分析 (5)
6.1三元组的转置 (5)
6.2三元组减法 (6)
6.3三元组的减法 (9)
6.4三元组的乘法 (12)
6.5十字链表的转置 (14)
6.6十字链表的加法 (15)
6.7十字链表的减法 (18)
6.8十字链表的乘法 (22)
7 系统测试 (25)
7.1三元组的转置 (25)
7.2三元组的加法 (26)
7.3三元组的减法 (26)
7.4三元组的乘法 (27)
7.5十字链表的转置 (27)
7.6十字链表的加法 (28)
7.7十字链表的减法 (28)
7.8十字链表的乘法 (29)
7.9总结 (29)
8结论 (29)
参考文献 (29)
摘要
随着计算机的普及,一句话引出题目…(小四楷体_GB2312),分析了三元组和十字链表的存储和各种运算的实现,利用C语言编程实现了稀疏矩阵的运算系统,该系统具有三元组十字链表存储下的稀疏矩阵转置、加法、减法、乘法的功能。

关键词:稀疏矩阵;计算机; 运算器
1 引言
1.1 问题的提出
矩阵是很多科学与工程计算问题中研究的数学对象。

因此,我们感兴趣的不是矩阵本身,而是如何存储矩阵的元,从而使矩阵的各种运算能有效地进行。

通常,用高级语言编制程序时,都是用二维数组来存储矩阵元,有的程序设计语言中还提供了各种矩阵运算,用户使用时很方便。

然而,在数值分析中,经常出现一些阶数很高的矩阵,同时在矩阵中有许多值相同的元素或者是零元素,有时为了节省存储空间,可以对这类矩阵进行压缩存储。

所谓压缩存储,就是指:为多个值相同的元只分配一个存储空间;对零元不分配空间。

1.2国内外研究的现状
目前已经可以用于人脸识别、子空间方法预处理技术稀疏近似逆按模最小特征值修正矩阵广义极小残余方法等方面。

1.3任务与分析
(1)给出算法并编程实现;
(2)任给实例并演示求解结果;
(3)给出时间复杂度分析;
(4)结合所完成题目,分析总结各算法所使用的算法设计技术,以及相应技术的基本思想。

2 程序的主要功能
2.1三元组的转置
将一个按三元组存储的稀疏矩阵进行转置。

2.2三元组的加法
将两个按三元组存储的稀疏矩阵进行相加并得出结果。

2.3三元组的减法
将两个按三元组存储的稀疏矩阵进行相减并得出结果。

2.4三元组的乘法
将两个按三元组存储的稀疏矩阵进行相乘并得出结果。

2.5十字链表的转置
将一个按十字链表存储的稀疏矩阵进行转置。

2.6十字链表的加法
将两个按十字链表存储的稀疏矩阵进行相加并得出结果。

2.7十字链表的减法
将两个按十字链表存储的稀疏矩阵进行相加并得出结果。

2.8十字链表的乘法
将两个按十字链表存储的稀疏矩阵进行相加并得出结果。

3程序运行平台
VC++6.0。

编译,链接,执行。

4总体设计
图4.1 系统总体框架图
主函数
三元组创建三












































5程序类的说明
•OLNode结构声明
typedef struct OLNode
{
int i,j;
int e;
struct OLNode *right,*down;
}OLNode,*OLink;
•Crosslist结构的声明
typedef struct
{
int mu,nu,tu;
OLink *rhead,*chead;
}CrossList;
•Triple结构的声明
typedef struct
{
int i,j;
int e;
}Triple;
•TSMatrix结构的声明
typedef struct
{
Triple data[maxsize];
int rpos[maxsize+1];
int nu,mu,tu;
}TSMatrix;
6 模块分析
6.1 三元组的转置
将一个按三元组存储的稀疏矩阵进行转置(非快速转置)。

void TransposeSMatrix(TSMatrix M,TSMatrix &T)//三元组的转置{
T.nu=M.mu;
T.mu=M.nu;
T.tu=M.tu;
int q=1;
for(int col=1;col<=M.nu;col++)
for(int p=1;p<=M.tu;p++)
if(M.data[p].j==col)
{
T.data[q].i=M.data[p].j;
T.data[q].j=M.data[p].i;
T.data[q].e=M.data[p].e;
q++;
}
}
int Compare(int a1,int b1,int a2,int b2)
{
if(a1>a2)return 1;
else if(a1<a2)
return -1;
else if(b1>b2)
return 1;
if(b1<b2)
return -1;
else
return 0;
}
6.2 三元组减法
用户再输入一个稀疏矩阵,系统将两个矩阵进行加运算并得出结果。

void AddTMatix(TSMatrix M,TSMatrix T,TSMatrix &S)//三元组相加
{
S.mu=M.mu>T.mu?M.mu:T.mu;
S.nu=M.nu>T.nu?M.nu:T.nu;
S.tu=0;
int ce;
int q=1;int mcount=1,tcount=1;
while(mcount<=M.tu&&tcount<=T.tu)
{
switch(Compare(M.data[mcount].i,M.data[mcount].j,T.data[tcount].i,T.data
[tcount].j))
{
case -1:
S.data[q].e=M.data[mcount].e;
S.data[q].i=M.data[mcount].i;
S.data[q].j=M.data[mcount].j;
q++;
mcount++;
break;
case 1:
S.data[q].e=T.data[tcount].e;
S.data[q].i=T.data[tcount].i;
S.data[q].j=T.data[tcount].j;
q++;
tcount++;
break;
case 0:
ce=M.data[mcount].e+T.data[tcount].e;
if(ce)
{
S.data[q].e=ce;
S.data[q].i=M.data[mcount].i;
S.data[q].j=M.data[mcount].j;
q++;
mcount++;
tcount++;
}
else
{
mcount++;
tcount++;
}
break;
}
}
while(mcount<=M.tu)
{
S.data[q].e=M.data[mcount].e;
S.data[q].i=M.data[mcount].i;
S.data[q].j=M.data[mcount].j;
q++;
mcount++;
}
while(tcount<=M.tu)
{
S.data[q].e=T.data[tcount].e;
S.data[q].i=T.data[tcount].i;
S.data[q].j=T.data[tcount].j;
q++;
tcount++;
}
S.tu=q-1;
}…
6.3三元组的减法
用户再输入一个稀疏矩阵,系统将两个矩阵进行加运、减算并得出结果。

void jianTMatix(TSMatrix M,TSMatrix T,TSMatrix &S)//三元组相减
{
S.mu=M.mu>T.mu?M.mu:T.mu;
S.nu=M.nu>T.nu?M.nu:T.nu;
S.tu=0;
int ce;
int q=1;int mcount=1,tcount=1;
while(mcount<=M.tu&&tcount<=T.tu)
{
switch(Compare(M.data[mcount].i,M.data[mcount].j,T.data[tcount].i,T.data [tcount].j))
{
case -1:
S.data[q].e=M.data[mcount].e;
S.data[q].i=M.data[mcount].i;
S.data[q].j=M.data[mcount].j;
q++;
mcount++;
break;
case 1:
S.data[q].e=-T.data[tcount].e;
S.data[q].i=T.data[tcount].i;
S.data[q].j=T.data[tcount].j;
q++;
tcount++;
break;
case 0:
ce=M.data[mcount].e-T.data[tcount].e;
if(ce)
{
S.data[q].e=ce;
S.data[q].i=M.data[mcount].i;
S.data[q].j=M.data[mcount].j;
q++;
mcount++;
tcount++;
}
else
{
mcount++;
tcount++;
}
break;
}
}
while(mcount<=M.tu)
{
S.data[q].e=M.data[mcount].e;
S.data[q].i=M.data[mcount].i;
S.data[q].j=M.data[mcount].j;
q++;
mcount++;
}
while(tcount<=M.tu)
{
S.data[q].e=-T.data[tcount].e;
S.data[q].i=T.data[tcount].i;
S.data[q].j=T.data[tcount].j;
q++;
tcount++;
}
S.tu=q-1;
}
6.4三元组的乘法
用户再输入一个稀疏矩阵,系统将其进行乘法运算并得出结果。

int MultSMatrix(TSMatrix M, TSMatrix N, TSMatrix &Q) //三元组相乘{
int arow,brow,ccol,i,t,ctemp[100],p,q,tp;
if(M.nu != N.mu)
return 0;
Q.mu=M.mu;
Q.nu =N.nu;
Q.tu =0;
if(M.tu*N.tu!=0)
{
for(arow=1;arow<=M.mu;++arow)
{
for(i=0;i<=N.nu;++i)
ctemp[i]=0;
Q.rpos[arow]=Q.tu+1;
if(arow<M.mu)
tp=M.rpos[arow+1];
else
tp=M.tu+1;
for(p=M.rpos[arow];p<tp;++p)
{
brow=M.data[p].j;
if(brow<N.mu)
t=N.rpos[brow+1];
else
t=N.tu+1;
for(q=N.rpos[brow];q<t ++q)
{
ccol=N.data[q].j;
ctemp[ccol]+=M.data[p].e*N.data[q].e;
}
}
for(ccol=1;ccol<=Q.nu;++ccol)
{
if(ctemp[ccol])
{
if(++(Q.tu)>maxsize)
return 1;
Q.data[Q.tu].i=arow,Q.data[Q.tu].j=ccol,Q.data[Q.tu].e=ctemp[ccol];
}
}
}
}
return 1;
}
6.5 十字链表的转置
void TurnSMatrix_OL(CrossList &M) //十字链表转置
{
int col,row;
OLink p,q;
for(col=1;col<=M.mu;col++)
{
q=p=M.rhead[col];
while(q)
{
row=p->i;
p->i=p->j;
p->j=row;
q=p->right;
p->right=p->down;
p->down=q;
}
}
}
6.6 十字链表的加法
int SMatrix_ADD(CrossList *A,CrossList *B) //十字链表相加{
OLNode *pa,*pb,*pre,*p,*cp[100];
int i,j,t;
t=A->tu+B->tu;
for(j=1;j<=A->nu;j++)
cp[j]=A->chead[j];
for(i=1;i<=A->mu;i++)
{
pa=A->rhead[i];
pb=B->rhead[i];
pre=NULL;
while(pb)
{
if(pa==NULL||pa->j>pb->j)
{
p=(OLink)malloc(sizeof(OLNode));
if(!pre)
A->rhead[i]=p;
else
pre->right=p;
p->right=pa;
pre=p;
p->i=i;
p->j=pb->j;
p->e=pb->e;
if(!A->chead[p->j])
{
A->chead[p->j]=cp[p->j]=p;
p->down=NULL;
}
else
{
cp[p->j]->down=p;
cp[p->j]=p;
}
pb=pb->right;
}
else if(pa->j<pb->j)
{
pre=pa;
pa=pa->right;
}
else if(pa->e+pb->e)
{
t--;
pa->e+=pb->e;
pre=pa;
pa=pa->right;
pb=pb->right;
}
else
{
t=t-2;
if(!pre)
A->rhead[i]=pa->right;
else
pre->right=pa->right;
p=pa;
pa=pa->right;
if(A->chead[p->j]==p)
A->chead[p->j]=cp[p->j]=p->down;
else
cp[p->j]->down=p->down;
free(p);
pb=pb->right;
}
}
}
A->mu=A->mu>B->mu?A->mu:B->mu;
A->nu=A->nu>B->nu?A->nu:B->nu;
return 1;
}
6.7十字链表的减法
int SMatrix_jian(CrossList *A,CrossList *B) //十字链表相减{
OLNode *pa,*pb,*pre,*p,*cp[100];
int i,j,t;
t=A->tu+B->tu;
for(j=1;j<=A->nu;j++)
cp[j]=A->chead[j];
for(i=1;i<=A->mu;i++)
{
pa=A->rhead[i];
pb=B->rhead[i];
pre=NULL;
while(pb)
{
if(pa==NULL||pa->j>pb->j)
{
p=(OLink)malloc(sizeof(OLNode));
if(!pre)
A->rhead[i]=p;
else
pre->right=p;
p->right=pa;
pre=p;
p->i=i;
p->j=pb->j;
p->e=-pb->e;
if(!A->chead[p->j])
{
A->chead[p->j]=cp[p->j]=p;
p->down=NULL;
}
else
{
cp[p->j]->down=p;
cp[p->j]=p;
}
pb=pb->right;
}
else if(pa->j<pb->j) {
pre=pa;
pa=pa->right;
}
else if(pa->e-pb->e) {
t--;
pa->e-=pb->e;
pre=pa;
pa=pa->right;
pb=pb->right;
}
else
{
t=t-2;
if(!pre)
A->rhead[i]=pa->right;
else
pre->right=pa->right;
p=pa;
pa=pa->right;
if(A->chead[p->j]==p)
A->chead[p->j]=cp[p->j]=p->down;
else
cp[p->j]->down=p->down;
free(p);
pb=pb->right;
}
}
}
A->mu=A->mu>B->mu?A->mu:B->mu;
A->nu=A->nu>B->nu?A->nu:B->nu;
return 1;
}
6.8十字链表的乘法
int MultSMatrix_OL(CrossList M, CrossList N, CrossList &Q) //十字链表相乘
{
int i, j, e;
OLink p0, q0, p, pl, pla;
if(M.nu!=N.mu)//检查稀疏矩阵M的列数和N的行数是否对应相等{
printf( "稀疏矩阵A的列数和B的行数不相等,不能相乘。

\n" );
return 0;
}
Q.mu=M.mu;
Q.nu=N.nu;
Q.tu=0;
if(!(Q.rhead=(OLink*)malloc((Q.mu+1)*sizeof(OLink))))
exit(-2);
if(!(Q.chead=(OLink*)malloc((Q.nu+1)*sizeof(OLink))))
exit(-2);
for(i=1;i<=Q.mu;i++)
Q.rhead[i] = NULL;
for(i=1;i<=Q.nu;i++)
Q.chead[i]=NULL;
for(i=1;i<=Q.mu;i++) //相乘
for(j=1;j<=Q.nu;j++)
{
p0 = M.rhead[i];
q0 = N.chead[j];
e = 0;
while(p0&&q0)//M第i行和N第j列有元素
{
if( p0->j > q0->i)
q0 = q0->down; //M的列大于N的行,则N的列指针后移else if(p0->j < q0->i)
p0 = p0->right;//M的列小于N的行,则M的行指针右移else //M的行等于N的列
{
e += p0->e * q0->e; //乘积累加
q0 = q0->down, p0 = p0->right;//移动指针
}
}
if(e)//乘积不为0
{
if(!(p = (OLink)malloc(sizeof(OLNode))))
exit(-2);
Q.tu++;//非零元素增加
p->i=i;
p->j=j;
p->e=e;
p->right=NULL;
p->down=NULL;//赋值,指针后移,将p插入十字链表行插入 if(Q.rhead[i]==NULL) //若p为该行的第1个结点
Q.rhead[i]=p =p; //p插在该行的表头且pl指向p(该行的最后一个结点)
else
pl->right=p,pl=p; //插在pl所指结点之后,pl右移列插入if(Q.chead[j] == NULL) //若p为该列的第一个结点
Q.chead[j] = p; //该列的表头指向p
else
{
//插在列表尾
pla = Q.chead[j];//pla指向j行的第1个结点
while(pla->down)
pla = pla->down;//pla指向j行最后一个结点
pla->down = p;
}
}
}
return 1;
}
7 系统测试
首先进入VC++6.0,打开“稀疏矩阵应用.cpp”,编译后执行文件,按系统提示操作。

7.1三元组的转置
三元组的转置,实现。

7.2 三元组的加法
三元组的加法,实现。

7.3 三元组的减法三元组的减法,实现。

7.4 三元组的乘法
三元组的乘法,实现。

7.5 十字链表的转置
十字链表的转置,实现。

7.6十字链表的加法
十字链表的加法,实现。

7.7 十字链表的减法十字链表的减法,实现。

7.8 十字链表的乘法
十字链表的乘法,实现。

7.9总结
通过上述测试,本系统实现了三元组和十字链表的转置、加、减、乘功能,且实现各个功能的时间复杂度均为 n平方。

8结论
通过上述测试,本系统用C语言在VC++6.0的平台上进行编程,实现了三元组和十字链表的转置、加、减、乘功能。

在进行稀疏矩阵的相加时,用十字链表更方便;进行相乘时,用三元组更方便。

参考文献
[1] 严蔚敏、吴伟民编著. 数据结构(C语言版). 北京:清华大学出版社,2007。

相关文档
最新文档