稀疏矩阵的十字链表加法
稀疏矩阵引用十字链表运算

稀疏矩阵应用摘要本课程设计主要实现在三元组存储结构与十字链表存储结构下输入稀疏矩阵,并对稀疏矩阵进行转置,相加,相乘操作,最后输出运算后的结果。
在程序设计中,考虑到方法的难易程度,采用了先用三元组实现稀疏矩阵的输入,输出,及其转置,相加,相乘操作的方法,再在十字链表下实现。
程序通过调试运行,结果与预期一样,初步实现了设计目标。
关键词程序设计;稀疏矩阵;三元组;十字链表1 引言•课程设计任务本课程设计主要实现在三元组存储结构与十字链表存储结构下输入稀疏矩阵,并对稀疏矩阵进行转置,相加,相乘操作,最后输出运算后的结果。
稀疏矩阵采用三元组和十字链表表示,并在两种不同的存储结构下,求两个具有相同行列数的稀疏矩阵A和B的相加矩阵C,并输出C;求出A的转置矩阵D,输出D;求两个稀疏矩阵A和B的相乘矩阵E,并输出E。
•课程设计性质数据结构课程设计是重要地实践性教学环节。
在进行了程序设计语言课和《数据结构》课程教学的基础上,设计实现相关的数据结构经典问题,有助于加深对数据结构课程的认识。
本课程设计是数据结构中的一个关于稀疏矩阵的算法的实现,包括在三元组和十字链表下存储稀疏矩阵,并对输入的稀疏矩阵进行转置,相加,相乘等操作,最后把运算结果输出。
此课程设计要求对数组存储结构和链表存储结构非常熟悉,并能熟练使用它们。
1.3课程设计目的其目的是让我们在学习完C、数据结构等课程基础上,掌握多维数组的逻辑结构和存储结构、掌握稀疏矩阵的压缩存储及转置,相加,相乘等基本操作,并用不同的方法输出结果,进一步掌握设计、实现较大系统的完整过程,包括系统分析、编码设计、系统集成、以及调试分析,熟练掌握数据结构的选择、设计、实现以及操作方法,为进一步的应用开发打好基础。
•需求分析2.1设计函数建立稀疏矩阵及初始化值和输出稀疏矩阵的值本模块要求设计函数建立稀疏矩阵并初始化,包括在三元组结构下和十字链表结构下。
首先要定义两种不同的结构体类型,在创建稀疏矩阵时,需要设计两个不同的函数分别在三元组和十字链表下创建稀疏矩阵,在输入出现错误时,能够对错误进行判别处理,初始化稀疏矩阵都为空值,特别注意在十字链表下,对变量进行动态的地址分配。
十字链表法存储稀疏矩阵

十字链表法存储稀疏矩阵稀疏矩阵是指其中大部分元素为0的矩阵。
在实际应用中,稀疏矩阵的存储和计算都会带来一定的困扰。
为了高效地存储和处理稀疏矩阵,我们可以使用十字链表法。
一、稀疏矩阵的特点稀疏矩阵的特点是其中绝大部分元素为0,而只有少部分非零元素。
这导致稀疏矩阵的存储空间浪费很大,因此需要采取一种有效的存储方式。
二、十字链表法的原理十字链表法是一种组合了链表和线性表的数据结构,用于存储稀疏矩阵。
具体实现如下:1. 定义两个链表headRow和headCol,分别用于存储行和列的头节点;2. 每个非零元素都对应一个结点,结点包含四个属性:行号row、列号col、值value以及指向下一个非零元素的指针nextRow和nextCol;3. headRow链表中的每个节点都指向同一行中的第一个非零元素,而headCol链表中的每个节点都指向同一列中的第一个非零元素;4. 非零元素之间通过nextRow和nextCol指针连接。
通过这种方式,我们可以高效地存储稀疏矩阵,并可以方便地进行矩阵的各种操作。
三、十字链表法的优势相比于其他存储稀疏矩阵的方法,十字链表法有以下几个优势:1. 空间利用率高:相比于使用二维数组存储,十字链表法可以大大减少存储空间的浪费,因为只存储非零元素及其位置信息;2. 支持高效的插入和删除操作:十字链表法可以通过调整指针的指向来进行插入和删除操作,而不需要像其他方法那样移动元素;3. 方便进行矩阵操作:通过十字链表法,我们可以方便地进行稀疏矩阵的各种操作,如矩阵相加、矩阵相乘等。
四、十字链表法的应用十字链表法广泛地应用于各个领域,特别是在图论和网络分析中。
在这些领域中,往往需要处理大规模的稀疏矩阵,而十字链表法能够有效地解决这个问题。
以社交网络为例,社交网络中的用户和用户之间往往存在着复杂的关系。
通过将社交网络建模成稀疏矩阵,可以使用十字链表法来存储和处理这些关系。
这样可以方便地进行各种网络分析操作,如查找某个用户的好友、计算两个用户之间的距离等。
稀疏矩阵的十字链表存储

稀疏矩阵的⼗字链表存储稀疏矩阵的压缩存储有⼏种⽅式,如:三元组顺序表、⾏逻辑链接的顺序表和⼗字链表。
使⽤链表存储的好处是:便于矩阵中元素的插⼊和删除。
例如:“将矩阵B加到矩阵A上”,那么矩阵A存储的元素就会有变动。
⽐如会增加⼀些⾮零元,或者删除⼀些元素(因为b ij+a ij=0)。
下图是矩阵M和M的⼗字链表存储:⼗字链表及其结点可⽤如下结构体表⽰:typedef struct OLNode{int i, j; // ⾮零元的⾏列下标ElemType e;struct OLNode *right, *down; // 向右域和向下域} OLNode, *OLink;typedef struct{OLink *rhead, *chead; // ⾏链表和列链表的头指针数组int mu, nu, tu; // 稀疏矩阵的⾏数、列数和⾮零元个数} CrossList;在通过代码创建⼗字链表时,要特别注意right、down和rhead、chead这些指针的赋值。
现在来看“将矩阵B加到矩阵A上”这个问题。
所要做的操作:a ij +b ij,其结果⼀共会有4种情况:1. a ij(b ij = 0)(不做变化)2. b ij(a ij = 0)(在A中插⼊⼀个新结点)3. a ij +b ij ≠ 0 (改变结点a ij的值域)4. a ij +b ij = 0 (删除结点a ij)假设指针pa和pb分别指向矩阵A和B中⾏值相同的两个结点,对于上述4种情况的处理过程为:1. 若“pa == NULL”或“pa->j⼤于pb->j”,则在矩阵A中插⼊⼀个值为b ij的结点。
并且需要修改同⼀⾏前⼀结点的right指针,和同⼀列前⼀结点的down指针。
2. 若“pa->j⼩于pb-j”,则pa指针右移⼀步。
3. 若“pa->j等于pb-j”,并且“pa->e + pb->e != 0”,则修改pa->e即可。
408考稀疏矩阵十字链表

408考稀疏矩阵十字链表稀疏矩阵是指大部分元素为零的矩阵。
在很多实际应用中,如图像处理、网络分析等领域,大型矩阵中的非零元素只占很小一部分。
为了节省存储空间和提高运算效率,我们可以使用稀疏矩阵来表示这些矩阵。
408考稀疏矩阵十字链表是一种常用的稀疏矩阵存储结构。
它通过将非零元素按行和列分别排列,并使用链表将它们连接在一起,从而实现对稀疏矩阵的高效存储和操作。
在408考中,稀疏矩阵十字链表是一种常用的数据结构,用于表示稀疏矩阵。
它是由徐仲恺老师于1971年提出的,是一种改进的稀疏矩阵链表存储结构。
相比于其他存储结构,稀疏矩阵十字链表具有存储空间小、插入和删除元素方便等优点。
稀疏矩阵十字链表的基本思想是将矩阵分解为行链表和列链表两部分,通过链表将非零元素连接起来。
具体来说,稀疏矩阵十字链表包含三个链表:行链表、列链表和非零元素链表。
行链表是由一组头指针组成的链表,每个头指针指向一行的第一个非零元素。
列链表是由一组头指针组成的链表,每个头指针指向一列的第一个非零元素。
非零元素链表则是将矩阵中的非零元素按照行优先的顺序连接起来。
通过这种方式,我们可以通过行链表和列链表快速找到某一行或某一列的非零元素,并可以在常数时间内插入和删除元素。
同时,由于非零元素链表是按照行优先的顺序连接的,因此可以按照矩阵的行优先顺序遍历非零元素。
使用稀疏矩阵十字链表存储稀疏矩阵可以大大减少存储空间的占用。
对于一个m×n的矩阵,如果非零元素的个数为k,那么稀疏矩阵十字链表的存储空间复杂度为O(k+max(m,n))。
相比之下,使用普通的二维数组存储矩阵需要O(m×n)的存储空间。
稀疏矩阵十字链表还可以实现矩阵的加法、减法和乘法等基本运算。
在进行运算时,我们只需要遍历非零元素链表,并根据链表中的信息进行相应的计算,而无需考虑矩阵中的零元素,从而提高了运算效率。
408考稀疏矩阵十字链表是一种高效的稀疏矩阵存储结构。
数据结构 课程设计 十字链表

数据结构课程设计十字链表xx学院一、问题的分析和任务定义:该设计是采用十字链表表示稀疏矩阵,并实现矩阵的加法运算。
还要检查有关运算的条件,并对错误的条件产生报警。
根据对该程序任务的理解,对本程序分别从以下几个方面进行分析: 1.输入数据的的类型和输入的范围该程序首先输入稀疏矩阵的行数和列数,再输入一个有非零元素的行号,有非零元素的列号,再输入非零元素的值,然后输入当前行下一个元素所在的列,如果该行只有一个非零元素就直接输入-1结束当前行的一组数据,如果还有其他的非零元素的话就输入当前行下一个非零元素所在的列,就这样,直到该当前行的非零元素输入完。
然后再输入当前列下一个非零元素的所在的行,其步骤与前一步相同。
其输入值都为稀疏矩阵的数据,类型都为整型。
2.输出数据的形式这样得到一个稀疏矩阵a,以同样的方法就可以得到另一个稀疏矩阵b,最后就可以得到稀疏矩阵a和稀疏矩阵b的和矩阵.输出是以稀疏矩阵的标准形式输出的。
输出值的有两种:一种是字符,一种是整数。
输出的字符型数据是稀疏矩阵的代号,输出的整型数据为稀疏矩阵的值。
3.测试数据测试数据一:测试数据二:稀疏矩阵的行数与列数:3 3 稀疏矩阵的行数与列数:3 3 矩阵a:矩阵b:矩阵a:矩阵b: 2 0 0 0 0 2 2 0 0 0 0 00 0 6 3 0 0 0 0 0 0 0 07 0 0 2 0 5 0 0 0 7 0 0二、概要设计和数据结构的选择:1.算法(程序)中用到的所有各种数据类型的定义:定义整型数据为int m,int n,分别代表矩阵的行和列;定义十字链表类型结点OLnode *h,*p分别代表为头结点开辟空间和指向下一结点;在主函数中定义OLnode *a,*b,分别表示a,b两个稀疏矩阵。
2.各程序模块之间的层次关系:程序中用到的函数:1 OLnode *create(int m,int n); 创建以十字链表表示的一个元素全为零的稀疏矩阵。
采用十字链表表示稀疏矩阵,并实现矩阵的加法运算

采用十字链表表示稀疏矩阵,并实现矩阵的加法运算课程设计所抽题目:采用十字链表表示稀疏矩阵,并实现矩阵的加法运算。
要求:要检查有关运算的条件,并对错误的条件产生报警。
问题分析和建立模型:本题目主要是运用所学知识,用十字链表的方法去表示稀疏矩阵,并使之可以在两矩阵间进行相加。
而后,若有错误,则对错误进行警报。
框架搭建:1选择File|New菜单项,弹出New对话框,选择Files标签,选中C++ Source File项,在File编辑器中输入项目名称“十字链表表示稀疏矩阵实现加法”,在Location编辑框中输入项目所在目录,按下OK 按钮即可。
2在操作界面中输入,程序代码。
(1)结构体和共用体的定义#include#include#define smax 45typedef int datatype;typedef struct lnode(2)建立稀疏矩阵的函数,返回十字链表头指针int i,j;struct lnode *cptr,*rptr;union{struct lnode *next;datatype v;}uval;}link;int flag=0;建立十字链表头结点head=(link *)malloc(sizeof(link));建立头结点循环链表for(i=1;i<=s;i++)(3)插入结点函数p=(link *)malloc(sizeof(link));p->i=0;p->j=0;p->rptr=p;p->cptr=p;cp[i]=p; cp[i-1]->uval.next=p;}cp[s]->uval.next=head;for(k=1;k<=t;k++){printf("\t 第%d个元素(行号i 列号j 值v,数字间用空格分隔):",k); scanf("%d%d%d",&i,&j,&v);p=(link *)malloc(sizeof(link));p->i=i;p->j=j;p->uval.v=v;q=cp[i];while((q->rptr!=cp[i])&&(q->rptr->j<j))< p="">q=q->rptr;p->rptr=q->rptr;q->rptr=p;q=cp[j];while((q->cptr!=cp[j])&&(q->cptr->i<i))< p="">q=q->cptr;p->cptr=q->cptr;q->cptr=p;}return head;(4)输出十字链表的函数link *p,*q;p=(link *)malloc(sizeof(link));p->i=i;p->j=j;p->uval.v=v;q=cp[i];while((q->rptr!=cp[i])&&(q->rptr->j<j))< p="">q=q->rptr;p->rptr=q->rptr;q->rptr=p;q=cp[j];while((q->cptr!=cp[j])&&(q->cptr->i<i))< p="">q=q->cptr ;p->cptr=q->cptr;q->cptr=p;(5)定义两个矩阵的非零元素,及两个矩阵的行和列数。
稀疏矩阵十字链表算法

稀疏矩阵十字链表算法稀疏矩阵是指矩阵中绝大多数元素为0的矩阵。
在实际应用中,很多矩阵都具有稀疏性,即元素中大部分为0,而只有少数非零元素。
对于这种类型的矩阵,为了节省内存空间并提高计算效率,可以采用稀疏矩阵的存储方式。
稀疏矩阵的一种常用存储方式是十字链表。
十字链表是一种将稀疏矩阵以链表形式存储的数据结构,它能够有效地表示稀疏矩阵的非零元素,并且能够方便地进行插入、删除和查找操作。
稀疏矩阵十字链表的基本思想是将矩阵中的每个非零元素存储为一个结点,并将这些结点以行列坐标的方式进行链接。
具体来说,稀疏矩阵十字链表由两个链表组成:行链表和列链表。
行链表是一个以行为主的链表,每个结点表示矩阵中的一行。
每个结点包含三个字段:行号、列号和值。
行链表中的结点按照行号从小到大的顺序进行排列,同一行中的结点按照列号从小到大的顺序进行排列。
列链表是一个以列为主的链表,每个结点表示矩阵中的一列。
每个结点也包含三个字段:行号、列号和值。
列链表中的结点按照列号从小到大的顺序进行排列,同一列中的结点按照行号从小到大的顺序进行排列。
通过行链表和列链表,可以方便地进行插入、删除和查找操作。
插入操作可以通过在行链表和列链表中找到对应的位置,将新结点插入到相应的位置上。
删除操作可以通过在行链表和列链表中找到对应的位置,将对应的结点删除。
查找操作可以通过在行链表和列链表中找到对应的位置,获取对应的结点。
稀疏矩阵十字链表算法的优点是能够有效地存储稀疏矩阵,并且可以方便地进行插入、删除和查找操作。
相比于其他存储方式,稀疏矩阵十字链表可以节省更多的内存空间,并且具有更高的计算效率。
总结来说,稀疏矩阵十字链表算法是一种有效地存储稀疏矩阵的方法。
通过行链表和列链表的链接,可以方便地进行插入、删除和查找操作。
稀疏矩阵十字链表算法在实际应用中具有广泛的应用,能够节省内存空间并提高计算效率。
稀疏矩阵十字链表算法

稀疏矩阵十字链表算法稀疏矩阵是指矩阵中大部分元素为0的矩阵。
在实际应用中,稀疏矩阵常常出现,比如图像处理、网络分析等领域。
由于稀疏矩阵中存在大量的0元素,传统的二维数组存储方式会造成内存空间的浪费,因此需要一种高效的数据结构来表示和存储稀疏矩阵。
稀疏矩阵十字链表算法就是一种解决这个问题的方法。
稀疏矩阵十字链表算法是一种基于链表的数据结构,用于表示和存储稀疏矩阵。
它通过两个链表来分别表示行和列,同时还使用了一个数据链表来存储非零元素的值和位置信息。
这种算法的核心思想是将稀疏矩阵的非零元素存储在链表中,并记录它们在矩阵中的位置信息,从而节省了存储空间。
具体来说,稀疏矩阵十字链表算法中,我们可以使用三个结构体来表示矩阵的行、列和非零元素。
其中,行和列的结构体包含了指向非零元素的指针和矩阵的维度信息。
非零元素的结构体包含了元素的值、行列坐标以及指向下一个非零元素的指针。
使用稀疏矩阵十字链表算法存储稀疏矩阵的好处是,它不仅节省了存储空间,还可以提高对稀疏矩阵的操作效率。
比如,对于稀疏矩阵的遍历操作,我们可以通过遍历链表的方式来实现,而不需要遍历整个矩阵,从而减少了时间复杂度。
除了存储和遍历操作,稀疏矩阵十字链表算法还可以支持其他一些常见的矩阵操作,比如矩阵的相加、相乘等。
对于这些操作,我们只需要按照链表的顺序进行遍历,并根据矩阵的位置信息进行计算即可。
稀疏矩阵十字链表算法的实现过程相对简单,但需要注意一些细节。
首先,我们需要确定稀疏矩阵的维度信息,并创建相应的行和列的链表头结点。
然后,我们可以按照行优先的方式遍历整个矩阵,将非零元素插入到链表中,并更新行和列的指针。
最后,我们可以根据需要进行各种矩阵操作。
稀疏矩阵十字链表算法是一种高效的存储和表示稀疏矩阵的方法。
它通过链表来存储非零元素,并记录它们在矩阵中的位置信息,从而节省了存储空间。
同时,它还可以支持各种常见的矩阵操作。
在实际应用中,稀疏矩阵十字链表算法可以提高程序的运行效率,减少内存的占用,是一种非常实用的数据结构算法。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
目录前言 (1)正文 (1)1.课程设计的目的和任务 (1)2.课程设计报告的要求 (1)3.课程设计的内容 (2)4.稀疏矩阵的十字链表存储 (2)5.稀疏矩阵的加法思想 (4)6.代码实现 (5)7.算法实现 (5)结论 (8)参考文献 (9)附录 (10)前言采用三元组顺序表存储稀疏矩阵,对于矩阵的加法、乘法等操作,非零元素的插入和删除将会产生大量的数据移动,这时顺序存储方法就十分不便。
稀疏矩阵的链接存储结构称为十字链表,它具备链接存储的特点,因此,在非零元素的个数及位置都会发生变化的情况下,采用链式存储结构表示三元组的线性更为恰当。
正文1.课程设计的目的和任务(1) 使我我们进一步理解和掌握所学的程序的基本结构。
(2) 使我们初步掌握软件开发过程的各个方法和技能。
(3) 使我们参考有关资料,了解更多的程序设计知识。
(4) 使我们能进行一般软件开发,培养我们的能力并提高我们的知识。
2.课程设计报告的要求(1)课程设计目的和任务,为了达到什么要求(2)课程设计报告要求(3)课程设计的内容,都包含了什么东西(4)稀疏矩阵和十字链表的基本概念,稀疏矩阵是怎么用十字链表存储(5)十字链表矩阵的加法(6)代码实现(7)算法检测3.课程设计的内容(1)根据所学知识并自主查找相关资料 (2)进行算法设计与分析(3)代码实现,组建并运行结果查看是否正确 (4)书写课程设计说明书4.稀疏矩阵的十字链表存储稀疏矩阵是零元素居多的矩阵,对于稀疏矩阵,人们无法给出确切的概念,只要非零元素的个数远远小于矩阵元素的总数,就可认为该矩阵是稀疏的。
十字链表有一个头指针hm ,它指向的结点有五个域,如图1所示。
row 域存放总行数m ,col 域存放总列数n ,down 和right 两个指针域空闲不用,next 指针指向第一个行列表头结点。
c o lr o w图1 总表点结点有S 个行列表头结点h[1],h[2],......h[s]。
结点结构与总表头结点相同。
Row 和col 域置0,next 指向下一行列表头结点,right 指向本行第一个非零元素结点,down 指向本列第一个非零元素结点如图2所示。
当最后一个行列表头结点的next 域指向总表头结点的hm 时,就形成循环链表,见图4的第一行。
Nextdownright图2 行列表头结点Nextdownright图3 非零元素结点⎥⎥⎥⎥⎥⎥⎦⎤⎢⎢⎢⎢⎢⎢⎣⎡--=30000000000201007003A 图4 稀疏矩阵非零元素结点结构也有五个域,与其他结点域结构相似,只有next 域为一变体域,可为val 域存放非零元素的值,row 和col 存放行下标值和列下标值,right 指向本行的下一个非零元素结点,down 指向本列的下一个非零元素结点。
稀疏矩阵中同一行的非零元素通过向右域right ,链接成一个带头结点的循环链表。
同一列的非零元素也通过向下域down 。
链接成一个带头结点的循环链表。
因此,每一个非零元素即是第i 行循环链表中的一个结点,又是第j 列循环链表中的一个结点。
这好比处于一个十字交叉路口上,故称这样的链表为十字链表。
例如,对于如图4所示的5行4列的稀疏矩阵A的十字链表如图5所示。
如图5可见,每一列链表的表头结点只需要用一个链域,指向该列中第一个非零元素,而每一行链表的表头结点只需right链域,指向该行中第一个非零元素,恰好他们的row和col域又同时为0,故这两组的表头结点可以合用(即第i行链表和第j列链表共用一个表头结点)这些表头结点本身又可以通过val域相链接(注意:val域在表头结点中为next域,是指向下一个表头结点的链域),加上附加结点(由指针hm指示),又组成一个带表头结点的循环链。
Hm所指结点为整个十字链表的表头结点,其row和col域的值分别为稀疏矩阵的行数和列数,hm为头指针。
由此,只要给定hm指针值,便可取得整个稀疏矩阵的全部信息。
图5 稀疏矩阵A的十字链表5.稀疏矩阵的加法思想如果运用带行指针向量和带列指针向量的存储结构进行系数矩阵的加法运算,设M和N是两个加法矩阵,Q是和矩阵,也就是结果矩阵。
M和N矩阵可以相加的前提条件是:M 和N矩阵是一样的,也就是说行数和列数的个数相同,M和N相加的结果矩阵就是一个一样大小的矩阵。
结果矩阵中每个行单链表也还是需要列号有序,它是对M和N中对应行单链表的按列号有序的合并结果。
当M和N中相应的行单链表的两个结点分别是一样的行号和列号时,如果他们的元素之和为0,就不在结果矩阵中建立结点,只有当元素的和不为0或者列号不一样时,才需要在结果矩阵中建立结点。
如果,M矩阵扫描完,N矩阵还没有扫描完,这个时候,直接就将N矩阵中的剩余的结点插入结果矩阵中。
6.代码实现矩阵中的元素在最后运行的时候由用户自己定义,根据用户输入的稀疏矩阵的行数、列数和非零元个数。
知道稀疏矩阵多少行、多少列以及有多少个非零元,然后依据非零元个数,输入非零元,仍然需要用户自己输入行号、列号以及非零值。
如果输入行数、列数和非零元个数为:5 4 3就表示这是一个5行4列3个非零元的稀疏矩阵用户自己输入行号、列号以及非零值,如:2 3 53 3 35 2 1表示第一个非零元在第2行,第3列,值为5;第二个非零元在第3行,第3列,值为3;第三个非零元在第5行,第2列,值为1。
所以此稀疏矩阵为:00 0 00 0 5 000 3 00 0 0 00 1 0 0再用同样的方法输入一个一样的5行4列的稀疏矩阵,设定行号、列号以及非零元值,利用稀疏矩阵的加法思想,将两个稀疏矩阵加起来得到结果矩阵。
7.算法实现运行开始界面,界面显示输入行数、列数和非零元素个数输入:3 3 3说明这个稀疏矩阵是三行、三列、三个非零元素,然后回车,界面再显示请输入一个非零元三元组<row,col,value>输入三元组:1 1 1说明在第一行、第一列的非零值是1,回车,界面显示输入一个非零元三元组按照上面的程序再依次输入:2 2 23 1 5矩阵A就完成了,然后界面得到稀疏矩阵A然后界面提示请输入行数、列数和非零元个数依照矩阵A的程序模式输入:3 3 41 1 22 1 13 1 13 3 3矩阵B也就完成了,然后界面得到稀疏矩阵B同时界面上也显示A+B=得到的结果矩阵结论M和N矩阵可以相加的前提条件是:M和N矩阵是一样的,也就是说行数和列数的个数相同,M和N相加的结果矩阵就是一个一样大小的矩阵。
结果矩阵中每个行单链表也还是需要列号有序,它是对M和N中对应行单链表的按列号有序的合并结果。
当M和N中相应的行单链表的两个结点分别是一样的行号和列号时,如果他们的元素之和为0,就不在结果矩阵中建立结点,只有当元素的和不为0或者列号不一样时,才需要在结果矩阵中建立结点。
参考文献[1]谭浩强编著.C++课程设计.北京:清华大学社,2004[2]S.B.Lippman,joie著.潘爱民译.C++Primer(3rd Edition)中文版.北京:中国电力出版社,2002[3]H.M.Deitel,Paul James Deitel著.薛万鹏译.C++程序设计教程.北京:机械工业出版社,2000[4]Stephen R.Savis著.C++ For Dummies 4th edition,IDG Books Worldwide,Inc.,2002[5]Harvey M.Deitel .Jack W.Davidson著.邱仲潘译.C++大学教程(第二版).北京:电子工业出版社,2002[6]James P.Cohoon.Jack W.Davidson著.刘瑞挺等译.C++程序设计(第三版).北京:电子工业出版社[7]Decoder编著.C/C++程序设计.北京:中国铁道出版社,2002[8]Brian Overland著.董梁等译.C++语言命令译解(第二版).北京:机械工业出版社,2002[9] H.M.Deitel,Paul James Deitel著.薛万鹏译.C/C++程序设计大全.北京:机械工业出版社.1997[10]Al Strevens,Clayton Walnum著.林丽闽等译.标准C++宝典.北京:电子工业出版社.2001[11]Michael J.Young著.Mastering Visual C++6.0 Sybex Inc.1999[12]Leen Ammeraal著.刘瑞挺等译.C++程序设计教程(第三版).北京:zhongguo 铁道出版社,2003[13] 吕凤翥著. C++语言程序设计.北方交通大学出版社,2003[14] 袁启昌著.C++语言程序设计.清华大学出版社,2004[15] 刘振安,刘燕君,孙忱C++语言课程设计.机械工业出版社,2007[16] 杨进才,沈显君,刘蓉编.C++语言程序设计教程.清华大学出版社,2006[17] 宋振会著. C++语言编程基础教程.清华大学出版社,2005附录#include<iostream>using namespace std;template<class Type>class MatrixNode;template<class Type>class LinkMatrix;template<class Type>istream &operator>>(istream &,LinkMatrix<Type>&); template<class Type>ostream &operator<<(ostream &,LinkMatrix<Type>&); template<classType>LinkMatrix<Type>operator+(constLinkMatrix<Type>&a,constLinkMatrix<Type> &b);template<class Type>class MatrixNode{friend class LinkMatrix<Type>;friend istream&operator>>(istream&,LinkMatrix<Type>&);friend ostream&operator<<(ostream&out, LinkMatrix<Type>&);friend LinkMatrix<Type> operator +(const LinkMatrix<Type> &a,const Link Matrix<Type>&b);private:int row,col;MatrixNode<Type>*right,*down;union{Type data;MatrixNode<Type>*next;};};template<class Type>class LinkMatrix{private:MatrixNode<Type> *head;void InsertInCol(MatrixNode<Type>*p);void DeleteInCol(MatrixNode<Type>*p);public:friend istream&operator>>(istream&in,LinkMatrix<Type>&);friend ostream&operator<<(ostream&out,LinkMatrix<Type>&);MatrixNode<Type>* Head(int i);LinkMatrix<Type>&operator +=(const LinkMatrix<Type> &a);friend LinkMatrix<Type> operator +(const LinkMatrix<Type> &a,const LinkMa trix<Type>&b);};template<class Type>istream&operator>>(istream&in,LinkMatrix<Type>&a){int m,n,terms,s;MatrixNode<Type>**cp,*p,*q;cout<<"输入矩阵的行数、列数、和非零元素个数"<<endl;in>>m>>n>>terms;if(n>m)s=n;else s=m;a.head=new MatrixNode<Type>;a.head->row=m;a.head->col=n;a.head->right=a.head->down=NULL;cp=new MatrixNode<Type>*[s+1];cp[0]=a.head;int i;for(i=1;i<=s;i++){p=new MatrixNode<Type>;p->row=p->col=0;p->right=p->down=p;cp[i]=p;cp[i-1]->next=p;}cp[s]->next=a.head;for(i=1;i<=terms;i++){cout<<"输入一个非零元三元组(row,col,value)"<<endl;p=new MatrixNode<Type>;in>>p->row>>p->col>>p->data;q=cp[p->row];while((q->right!=cp[p->row]&&(q->right->col<p->col)))q=q->right;p->right=q->right;q->right=p;q=cp[p->col];while((q->down!=cp[p->row]&&(q->down->col<p->col)))q=q->down;p->down=q->down;q->down=p;}delete[]cp;return in;}template<class Type> MatrixNode<Type>* LinkMatrix<Type>::Head(int i){MatrixNode<Type>*a;a=head->next;for(int j=1;j<i;j++){a=a->next;}return a;}template<class Type>void LinkMatrix<Type>::InsertInCol(MatrixNode<Type>*p) {MatrixNode<Type>*pre,*ch=Head(p->col);pre=ch;while(pre->down!=ch&&pre->down->row<p->row)pre=pre->down;p->down=pre->down;pre->down=p;}template<class Type>void LinkMatrix<Type>::DeleteInCol(MatrixNode<Type>*p) {MatrixNode<Type>*pre,*ch=Head(p->col);pre=ch;while(pre->down!=ch&&pre->down!=p)pre=pre->down;if(pre->down==p){pre->down=p->down;delete p;}//else throw invalid_arguement("No such a Node to be deleted in Delet eInCol()");}template<class Type> //重载符合赋值运算符+=LinkMatrix<Type>&LinkMatrix<Type>::operator +=(const LinkMatrix<Type> &a) {MatrixNode<Type> *pre,*pa,*h,*ah,*p,*tmp;if(head->col !=a.head->col||head->row !=a.head->row)//非同型矩阵不可相加cout<<"The two matrice aren't isomorphic!";//throw domain_error("The two matrice aren't isomorphic!");h=head->next;ah=a.head->next; //h、ah指向当前处理行的头结点while(h !=head){ //逐一处理各行pre=h; p=h->right; //p指向被加矩阵的当前结点,pre指向其前驱pa=ah->right; //pa分别指向加矩阵的当前结点while(pa !=ah) { //处理当前行if(p !=h&&(p->col<pa->col)){ //若被加矩阵的列标更小,则比较下一个pre=p; p=p->right;}else if(p==h||p->col>pa->col){ //若加矩阵的列标更小,则插入tmp=new MatrixNode<Type>(*pa)pre->right=tmp; //在行链表中插入pa复制结点tmptmp->right=p;InsertInCol(tmp); //在列表中插入tmppre=tmp; //当前指针p的前驱变为tmppa=pa->right;}else { //列标相同,则做加法p->data +=pa->data;if(!p->data) { //和为0,则删除之(行、列都要删除)tmp=p;p=p->right;pre->right=p;//在行链表中将tmp摘下DeleteInCol(tmp); //在列链表中将tmp删除}pre=p;p=p->right;pa=pa->right;}}h=h->next; ah=ah->next; //处理下一行}return *this;}template<class Type> //重载加法运算符+LinkMatrix<Type> operator +(const LinkMatrix<Type> &a,const LinkMatrix<Typ e> &b){LinkMatrix<Type> c(a); //复制构造函数得到被加矩阵A的一个副本放在矩阵C中c+=b;return c;}template<class Type>ostream & operator<<(ostream & out ,LinkMatrix<Type>& a) {for(int i=1;i<=a.head->row;i++){MatrixNode<Type>*b=a.Head(i);b=b->right;for(int j=1;j<=a.head->col;j++){if(b->row==i&&b->col==j){cout<<b->data<<' ';b=b->right;}else{cout<<'0'<<' ';}}cout<<endl;}return out;}int main(){LinkMatrix<int>a,b,c;cin>>a;cout<<"A矩阵为:\n"<<a<<endl;cin>>b;cout<<"B矩阵为:\n"<<b<<endl;c=a+b;cout<<"A+B=\n"<<c<<endl;system("pause");return 0;}。