《矩阵的加减法》由会员分享,可在线阅读,更多相关《矩阵的加减法(14页珍藏版)》请在金锄头文库上搜索。
1、合肥学院计算机科学与技术系课程设计报告20082009 学年第二学期课程 数据结构与算法课程设计名称矩阵的加法运算问题学生姓名杨扬学号0704032039专业班级07网络工程(2)指导教师张贯虹 屠菁 2009年6月题目:(矩阵的加法运算问题)设计程序完成如下要求:采用十字链表表示稀疏矩阵,并实现矩阵的加法运算。要求:要检查有关运算的条件,并对错误的条件产生报警。一、问题分析和任务定义此程序需要完成如下要求:使用十字链表存储结构存储稀疏矩阵并实现两个矩阵的相加运算。实现本程序需要解决一下几个问题:1、如何用一个十字链表来表示稀疏矩阵。2、十字链表如何创建。3、如何实现稀疏矩阵的加法运算。4、对
2、错误的条件产生警报。5、如何把矩阵输出。本问题的关键和难点在于编写算法实现两个稀疏矩阵的相加运算使得相加后的矩阵仍然是稀疏矩阵。在链表中,每个非0元素可用一个含有五个域的结点表示: ijvcptrrptr 图1 十字链表结点结构 其中:i , j ,v 三个域分别表示该元素所在的行、列和非0元素的值。行指针域 rptr 用以链接同一行中下一个非0元素;列指针域 cptr 用以链接同一列中下一个非0元素。存储时,每个非0元既是某个行链表中的一个结点,又是某个列链表中的一个结点;整个矩阵构成了一个十字交叉的链表,如下图: rhead Mchead 图2 稀疏矩阵的十字链表存储示例 可用两个分别存储
3、行链表Mrhead和列链表Mchead的头指针的一维数组表示十字链表。使用十字链表建立稀疏矩阵后就是矩阵相加的运算问题。对于稀疏矩阵来说,其存储结构决定了它不可以按照普通矩阵的加法来运算。对于两个稀疏矩阵A、B相加,每个位置(i,j)上的和只可能有三种情况:aij+bij、aij(bij=0)、bij (aij =0)。可以将稀疏矩阵Bm*n加到稀疏矩阵Am*n上,若aij+bij不等于0,则只需改变aij的值;若aij+bij等于0,则应从十字链表A中删除aij对应的结点;若和值为bij,则只需在十字链表A中添加一个结点。为实现该过程可以从矩阵的第一行逐行进行。二、数据结构的选择和概要设计十
4、字链表使用的是链接存储的方式。其结点类型为olnode,每个结点中除了描述非0元素所在的行号i、列号j、及非0元素的值v以外,还有两个指针域;行指针域rptr和列指针域cptr。行指针域 rptr 用以链接同一行中下一个非0元素;列指针域 cptr 用以链接同一列中下一个非0元素。在十字链表用以olnode类型的一维指针数组rheadm和cheadn来表示所有的行链表和列链表。这两个指针数组及稀疏矩阵中非零元素个数t一起构成crosslist类型。为了实现两个矩阵相加的功能需要创建十字链表M,然后用M来存储矩阵A和矩阵B。判断A、B两个矩阵是否满足相加条件,如果可以相加则逐个比较两个矩阵对应i
5、的行链表A-rheadi与B-rheadi上的每一个结点*a和*b:若两个结点的列号相同(a-j=b-j),则将它们值域中的内容相加(a-=a-v+b-v);若它们的和a-v等于0,则将结点*a从行链表A-rheadi及相应的列链表中删除。若行链表B-rheadi上结点*b的列号小于行链表A-rheadi上结点*a的列号,则将结点*b插到行链表Arheadi上结点*a之前。根据结点*b的列号将其插入到十字链表A合适的列链表中。若行链表B-rheadi上结点*b的列号大于行链表A-rheadi上结点*a的列号,则令a=a-rptr,并重复以上步骤直到对应的链表比较完毕。另外,为便于插入与删除结点
6、,还应设立一些辅助指针;在A的行链表上设置一个pre指针,使其指向*a的前驱结点;在A的每一个列链表上设置一个指针acolj,它的初始值与列链表的头指针相同,即acolj= A-rheadi。另外题目要求要检查有关运算的条件,并对错误的条件产生报警。这里判断矩阵是否可以相加的条件,需要用到线性代数中矩阵能够相加的条件即:两个待加的矩阵具有相同的行数和列数。因此可已在矩阵执行相加函数前调用判断函数经行判断,符合相加条件则执行相加算法;不符合则提示出错并提供修改的操作。三、详细设计和编码、本程序十字链表的建立和相加算法为设计的核心内容。十字链表创建的过程可描述如下:首先申请一个存放crosslis
7、t类型的数据所需要的存储空间。这包括存放各行链表列链表首元素结点地址的行、列指针数组的空间,以及存放稀疏矩阵的非0元素个数所需的存储空间。M=(crosslist *)malloc(sizeof(crosslist);接下来,分别给M-m、M-n、 M-t、M- rheadK、 M- rheadN赋值:scanf(%d%d%d,&(M-m),&(M-n),&(M-t);for(i=0;im;i+)M-rheadi=NULL;for(i=0;in;i+)M-cheadi=NULL;然后,输入所有的非0元素的三元组,生成相应的结点,并根据其行号将该结点插入到相应的行链表中:p=(olnode *)malloc(sizeof(olnode);scanf(%d%d%d,&(p-i),&(p-j),&(p-v);如果该行链表为空,或者当前结点的列号比该行链表中第一个结点的列号小,则将该结点作为首元素结点插入到该行链表中。if(M-rheadp-i=NULL)|(M-rheadp-i-j)(p-j)p-rptr=M-rheadp-i;M-rheadp-i=p;否则,查找该行链表中的各结点的列号