矩阵的加法运算问题数据结构与算法课程设计报告Word文件下载.docx
- 文档编号:16294350
- 上传时间:2022-11-22
- 格式:DOCX
- 页数:32
- 大小:196.39KB
矩阵的加法运算问题数据结构与算法课程设计报告Word文件下载.docx
《矩阵的加法运算问题数据结构与算法课程设计报告Word文件下载.docx》由会员分享,可在线阅读,更多相关《矩阵的加法运算问题数据结构与算法课程设计报告Word文件下载.docx(32页珍藏版)》请在冰豆网上搜索。
=1020
009
(b)两个行列数不相同的矩阵
3000000
0060
600+0000
2000
0000000
输出:
不能进行加法运算,矩阵的行数和列数应分别相同!
!
(c)两个以上的矩阵相加
0000010000
060000-3000
50300+00000+
0000000000
00050
20000
10000
00000
05000
10050
23000
=60300
00000
05000
二、数据结构的选择和概要设计
1、主界面设计:
为了实现对稀疏矩阵的多种算法功能的管理,首先设计一个含有多个菜单项的主控菜单子程序以链接系统的各项子功能,方便用户交互式使用本系统。
本系统登录菜单运行界面如图1-1所示
图1-1
除了登录矩阵计算器菜单之外,还有计算器的选项菜单,如图1-2所示
图1-2
2、存储结构设计:
本系统采用十字链表结构存储稀疏矩阵的具体信息。
其中:
全部结点的信息用头结点为指针数组的链表存储;
每个结点里面包含行号(i),列号(j)和对应的数值(v),它们是整型数据,还有两个指针cptr、rptr分别是行指针域和列指针域,属于node结构体。
全部的信息用结构体(CrossList)包含,包括指针数组(rhead和chead)和总共的行数(m),列数(n)以及非零元素的个数(t)。
3.系统功能设计:
本系统要完成稀疏矩阵的加法,就需要建立稀疏矩阵,则用Creat_CrossList()实现,然后要依次读取信息,即向Creat_CrossList()创建的空链表中插入结点,就是从键盘读取信息,行号,列号以及非零元素的值,这需要通过函数Insert_CrossList()来完成这个工作。
在该课程设计中,最主要的就是实现矩阵的加法,即矩阵A+B,该功能通过调用函数Matrixpuls_CrossList();
来实现的。
要输出通过输出函数Display_CrossList();
来完成。
但是在程序执行的过程中,调用相加函数之前,需要判断两个矩阵A与B是否符合矩阵相加的条件。
最后就是需要退出程序的操作,可以根据功能菜单选择进行操作,就可以退出程序。
4、模块设计:
本程序包含2个模块:
主程序模块和各功能实现模块。
调用关系如图1-3所示。
图1-3模块调用示意图
5、系统子程序及功能设计
(1)CrossList*Creat_CrossList()//创建矩阵
(2)CrossList*Insert_CrossList(CrossList*M)//往矩阵中插入结点信息
(3)voidDispaly_CrossList(CrossList*M)//输出矩阵信息
(4)CrossList*Matrixpuls_CrossList(CrossList*A,CrossList*B)//矩阵相加
(5)intJudge_CrossList(CrossList*A,CrossList*B)//判断矩阵是否符合相加条件
(6)voidLogin_Menu()//登录菜单
(7)voidLogin_Pcmd()//登录函数
(8)voidmain()//主函数,设置窗口模式和窗口标题,以及调用各个子函数
(9)Select_Menu()//计算器功能选择菜
三、详细设计和编码
1、数据类型的定义
//结点类型
typedefstructnode
{inti,j,v;
//元素的行标、列标、值域
structnode*rptr,*cptr;
//行指针域、列指针域
}OLNode;
//十字链表类型
typedefstruct
{OLNode*rhead[K],*chead[N];
//存放行链表及列链表的首地址
intm,n,t;
//矩阵的行数、列数、非灵元素个数
}CrossList;
2.系统主要子程序详细设计
(1)主程序模块设计及用户工作区模块设计
//设置窗口的大小,颜色,标题
system("
cls"
);
//清屏
system("
color17"
//设置窗口的背景颜色
modeconcols=60lines=25"
//设置窗口模式
title欢迎使用矩阵加法计算器"
//设置窗口标题
以后根据程序的提示执行操作,选择自己需要执行的操作
(2)以下是稀疏矩阵操作各子函数的定义:
①建立稀疏矩阵:
输入行数,然后判断行数是否符合要求,即行数是否大于0,若不符合则需要重新输入数据
printf("
\n%c输入行数:
"
1);
//输入行数
scanf("
%d"
&
(M->
m));
while(M->
m<
=0)
{printf("
\n%c您输入的行数不符实际..."
printf("
\n\n%c请重新输入行数:
}
输入列数,然后判断列数是否符合要求,即列数是否大于0,若不符合则需要重新输入数据
\n%c输入列数:
//输入列数
n));
n<
\n%c您输入的列数不符实际..."
\n\n%c请重新输入列数:
}
输入非零元素的个数,然后判断个数是否符合要求,即列数是否大于等于0,若不符合则需要重新输入数据
\n%c输入非零元素数个数:
//输入非零元素个数
t));
t<
0)
\n%c您输入的非零元素数个数不符实际..."
\n\n%c请重新输入非零元素数个数:
判断创建矩阵的行数×
列数>
=非零元素的个数,比如5行3列,总共可以存储15个元素,而输入的时候可能会输入的数大于15,比如20,造成无法存储,这就需要重新创建矩阵。
while(M->
t>
m*M->
n))/
\n%c不符合条件...\n"
\n"
%c重要提示:
输入失败的原因是非零元素的个数>
行数x列数\n"
\n%c重新输入..."
pause"
//暂停
}}
②输出稀疏矩阵:
通过for循环,来输出矩阵中的所有的非零元素的信息
for(a=1;
a<
=M->
m;
a++)
{p=M->
rhead[a];
while(p!
=NULL)
\t%c<
%d,%d,%d>
\t"
1,p->
i,p->
j,p->
v);
p=p->
rptr;
}
③插入结点信息:
初始化行链表,列链表为空
for(i=1;
i<
i++)//行链表置空
M->
rhead[i]=NULL;
for(i=1;
n;
i++)//列链表置空
chead[i]=NULL;
向创建的空矩阵中插入结点信息,不符合要求就需要重新输入。
比如输入的一个结点的信息的行号、列号大于行数或者列数。
\n%c第%d个元素为:
1,h);
%d%d%d"
p->
i,&
j,&
while(p->
i>
M->
m||p->
j>
n)//判断输入是否符合要求
\n%c重要提示:
该元素的行号或者列号超出范围..."
\n%c重新输入第%d个元素:
将结点插入到行链表的指针数组中,用数组rhead[]来存储
if((M->
rhead[p->
i]==NULL)||((M->
i]->
j)>
(p->
j)))//当该元素所在的行首地址为空或当前结点的列号比该列行链表中第一个结点的行号小
{p->
rptr=M->
i];
//将该结点作为首元素结点插入到该行链表中
i]=p;
else
//查找该行链表中的个结点的列号,将该结点按列号的顺序插入到该行链表中
{u=M->
q=M->
while(q!
=NULL)//指针后移找到比待插入结点列号大的元素地址
{if(q->
j)break;
u=q;
q=q->
p->
rptr=q;
//插入结点
u->
rptr=p;
将结点插入到列链表的指针数组中,用数组chead[]来存储
if((M->
chead[p->
j]==NULL)||((M->
j]->
i)>
i)))//根据列号将结点插入到相应的列链表中
cptr=M->
j];
//将该结点作为首元素结点插入到该列链表中
j]=p;
else
cptr;
cptr=q;
cptr=p;
④矩阵相加函数:
令a,b分别指向A和B的第一个行链表
i=1
a=A->
rhead[i];
//将矩阵A第i行的首地址赋给a
b=B->
//将矩阵B第i行的首地址赋给b
并初始化指针acol[]
=A->
i++)
acol[i]=A->
chead[i];
逐行比较行链表A->
rhead[i]与B->
rhead[i]上的每一个结点*a和*b,直到链表B->
rhead[i]中所有非0元结点均比较完毕:
ⅰ、若链表A->
rhead[i]已比较完毕,或结点*b的列号小于结点*a的列号,则在链表A->
rhead[i]中插入一个*b的复制结点:
if(a==NULL||a->
b->
j)//若a地址为空或列号大于b的列号
{if(pre==NULL)//a的前驱为空时
A->
rhead[i]=p;
//将p插入到该行头结点之前
pre->
//将p插到a结点之前
rptr=a;
pre=p;
//a的前驱变为p结点
同时结点*p也插入到相应的列链表中。
ⅱ、若结点*b的列号大于结点*a的列号,则在链表A->
rhead[i]中查到列号大于*b的列号结点的前驱结点,并插入一个*b的复制结点*p;
即若*c的后继结点的列号大于*b的列号,则*p插入到*c后:
while(a!
=NULL&
&
a->
j<
j)
{pre=a;
a=a->
{pre->
p->
pre=p;
//a的前驱变为p结点}
else//否则两结点列号相同
{a->
v=a->
v+b->
v;
//将两节点数值相加赋给a
if(a->
v==0)//若相加后为值为0
{if(pre==NULL)//a的前驱为空时
A->
rhead[i]=a->
//将a结点删除
elsepre->
rptr=a->
//否则,将a的前驱后移一位
p=a;
//p指向被删除的结点
a=a->
//a后移一位
if(A->
j]==p)//p指向的结点为所在列的首元素时
{A->
j]=p->
//将p从列链表中删除
acol[p->
}
else//找到p所在列链表的前驱结点
{while(acol[p->
cptr!
=p)
j]=acol[p->
cptr=p->
}//将p从列链表中删除
free(p);
}//释放p指向结点的空间
else//若相加后为值不为0
{pre=a;
//pre指向a
}}//a后移一位
break;
同时,结点*p也插入到相应的列链表中。
ⅲ、若结点*b的列号等于结点*a的列号,将*b结点的值加到*a结点上:
if(a!
j==b->
j)//如果两结点列号相同
a->
此时,若a->
v!
=0;
则无需其他操作;
否则,在十字链表A中删除该结点。
在行链表中删除该结点:
if(pre==NULL)//a的前驱为空时
//将a结点删除
同时,在列地址A->
j]中删除该结点
若本行不是最后一行,则令a和b指向下一行行链表的首元素结点,转至
(2);
否则,算法结束。
⑤判断函数:
intJudge_CrossList(CrossList*A,CrossList*B)
{if(A->
m==B->
m&
A->
n==B->
n)
return0;
//符合返回0
elsereturn1;
}//不符合返回1
该函数是用于判断矩阵A和矩阵B是否符合相加条件,即A和B的行数和列数是否相等,相等返回0,不相等返回1
四、上机调试
1、语法错误及修改:
出现的语法问题是要在于子函数和变量定义,括号的配对,关键字和函数名称的书写,以及一些库函数的规范使用。
这些问题均可以根据编译器的警告提示,对应的将其解决。
2、逻辑问题修改和调整:
①判断矩阵A和B的相加问题:
由于判断两矩阵是否符合相加条件,就是矩阵A和B的行数和列数是否相等,相等就执行加法运算,若不相等就需要修正矩阵A或者B,就需要重新创建,而在程序中没有加入
if(r=='
A'
)//修改矩阵A
{printf("
\n%c矩阵A...\n"
A=Creat_CrossList();
Insert_CrossList(A);
if(r=='
B'
)//修改矩阵B
\n%c矩阵B...\n"
B=Creat_CrossList();
Insert_CrossList(B);
加入后就可以随时修改其中一个矩阵了,使其符合相加条件。
②在矩阵加法中,由于该程序是书上的,所以可以用现成的,但是在程序中有个问题,就是当a->
v时,只有当相加结果为零的情况
if(a->
{if(pre==NULL)//a的前驱为空时
else
pre->
//将a的前驱后移一位
//p指向被删除的结点
//a后移一位
{A->
{while(acol[p->
}//将p从列链表中删除
而没有相加不等于零的情况,即a-v!
=0,因此需要加入如下函数
else//若相加后为值不为0
//pre指向a
}//a后移一位
五、测试结果及其分析
1、系统运行登陆界面如图1-4所示:
图1-4
2、系统的功能选项界面,如图1-5所示:
图1-5
3、创建矩阵A并输入矩阵A,如图1-6所示:
图1-6
4、创建矩阵B,并输入B,如图1-7所示:
图1-7
5、矩阵A+B,由上面矩阵A和B的截图可知,A与B不符合相加条件,产生错误提示并修正。
如图1-8所示:
图1-8
修改之后输出矩阵A+B的结果,如图1-9所示:
图1-9
6、退出程序,如图1-10所示:
图1-10
六、用户使用说明
本程序执行文件为:
矩阵的加法运算问题.exe
进入本系统之后,会显示登陆界面菜单,根据提示操作。
接着是进入欢迎登陆并使用矩阵加法计算器,然后按任意键继续,输入密码和账号,登陆即可以使用计算器了。
然后根据计算器界面的提示选择您想要的功能操作。
七、参考文献
[1]王昆仑,李红.数据结构与算法.北京:
中国铁道出版社,2006年5月。
[2]严蔚敏数据结构与算法视频
八、附录
#include"
stdio.h"
malloc.h"
#defineK50//预设稀疏矩阵的行数
#defineN50//预设稀疏矩阵的列数
stdlib.h"
string.h"
//创建空十字链表
CrossList*Creat_CrossList()
{CrossList*M;
M=(CrossList*)malloc(sizeof(CrossList));
\n%c您输入的非零元
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 矩阵 加法 运算 问题 数据结构 算法 课程设计 报告