稀疏矩阵应用.
数据结构之稀疏矩阵稀疏矩阵的存储方式和操作分析

数据结构之稀疏矩阵稀疏矩阵的存储方式和操作分析稀疏矩阵是指矩阵中大部分元素为零的特殊矩阵。
在实际应用中,稀疏矩阵经常出现,如图像处理、网络分析和科学计算等领域。
对于稀疏矩阵的存储和操作是数据结构中的重要内容。
本文将介绍稀疏矩阵的存储方式和相关操作的分析。
一、稀疏矩阵存储方式稀疏矩阵的存储方式有多种,其中三元组顺序表和二维数组是比较常用的方法。
1. 三元组顺序表三元组顺序表是一种基于行优先存储的方式,可以将稀疏矩阵以非零元素的形式存储起来。
主要包括行号、列号和元素值三个信息。
以一个4x5的稀疏矩阵为例,其中有三个非零元素分别为A[1][2]=3, A[2][3]=4, A[3][4]=5。
可以使用三元组顺序表来存储:```行号列号元素值1 2 32 3 43 4 5```三元组顺序表的优点是可以节省存储空间,同时也方便进行矩阵的操作。
但是在进行元素的查找和修改时,效率较低。
2. 二维数组二维数组是一种常见的矩阵表示方法,可以直接使用二维数组来表示稀疏矩阵。
其中非零元素的位置用实际的值表示,其余位置用零值表示。
以同样的4x5的稀疏矩阵为例,使用二维数组存储如下:```0 0 0 0 00 0 3 0 00 0 0 4 00 0 0 0 5```二维数组的优点是简单直观,并且可以快速进行元素的查找和修改。
但当稀疏矩阵的规模较大时,会造成较高的存储资源浪费。
二、稀疏矩阵的操作分析对于稀疏矩阵的操作,主要包括矩阵的转置、相加、相乘等。
1. 转置操作稀疏矩阵的转置是指将原始矩阵的行与列对调。
对于三元组顺序表来说,转置操作主要涉及到行号和列号的交换。
而对于二维数组来说,可以直接在取值的时候将行号和列号对调即可。
2. 相加操作稀疏矩阵的相加操作是指将两个矩阵对应位置的元素相加。
对于三元组顺序表来说,可以通过遍历两个矩阵的非零元素,并将其对应位置的元素相加。
而对于二维数组来说,可以直接将对应位置的元素相加即可。
3. 相乘操作稀疏矩阵的相乘操作是指将两个矩阵相乘得到一个新的矩阵。
稀疏矩阵乘法 并行

稀疏矩阵乘法并行全文共四篇示例,供读者参考第一篇示例:稀疏矩阵乘法是一种重要的数值计算问题,它在很多领域都有着广泛的应用,比如图像处理、机器学习等。
由于稀疏矩阵的特性是大部分元素都是0,只有少量非零元素,所以传统的矩阵乘法算法在处理稀疏矩阵时会浪费大量的计算资源。
为了解决这个问题,人们提出了一种并行计算的方法,即利用多个处理器同时计算矩阵乘法,从而提高计算效率。
在并行计算中,稀疏矩阵乘法也有着自己的特点和挑战。
稀疏矩阵的非零元素分布在整个矩阵中,处理起来比较困难。
矩阵乘法的计算量随着非零元素的增加而增加,所以需要合理地分配计算资源和任务。
稀疏矩阵乘法的并行计算需要考虑通信开销和负载均衡,以充分利用多个处理器的计算能力。
为了解决上述问题,人们提出了一些并行的稀疏矩阵乘法算法。
其中比较有代表性的是基于CSR(Compressed Sparse Row)格式的算法。
CSR格式是一种压缩存储稀疏矩阵的方法,它将矩阵分成三部分:非零元素数组、列索引数组和行偏移数组。
基于CSR格式的算法在并行计算中能够有效地减少通信开销,提高计算效率。
还有一些其他的并行稀疏矩阵乘法算法,比如基于COO (Coordinate)格式、基于Ecoo(Ellpack-Chebyshev)格式等。
这些算法都有着自己的特点和适用场景,可以根据具体的问题选择合适的算法。
在并行计算中,负载均衡是一个非常重要的问题。
负载不均衡会导致一些处理器的计算资源被浪费,影响整体的计算效率。
为了解决负载均衡问题,人们提出了一些方法,比如动态任务分配、静态任务划分、自适应任务调度等。
这些方法能够根据任务的计算量和数据分布特点,合理地分配任务,从而提高计算效率。
除了负载均衡,通信开销也是一个需要考虑的重要问题。
在并行计算中,处理器之间需要进行通信,传递计算结果和数据,这会导致一定的开销。
为了减小通信开销,人们提出了一些方法,比如数据压缩、异步通信、消息合并等。
matlab中稀疏矩阵

matlab中稀疏矩阵创建稀疏矩阵的步骤。
最后,我们将讨论稀疏矩阵的应用场景以及如何在MATLAB中进行操作。
第一步:了解稀疏矩阵稀疏矩阵是一种特殊类型的矩阵,其中大部分元素为0。
相比之下,密集矩阵大多数元素都是非零的。
由于其绝大多数元素为0,稀疏矩阵占用较少的内存空间,并且在某些应用中可以大大加快计算速度。
因此,对于具有大量零元素的矩阵,使用稀疏矩阵存储和操作数据是非常有效的。
第二步:创建稀疏矩阵在MATLAB中,我们可以使用'sparse'函数创建稀疏矩阵。
该函数采用三个输入参数:行索引向量,列索引向量和对应于非零元素的值向量。
这些输入参数的长度必须相同,且行索引和列索引不能超过矩阵的尺寸。
例如,假设我们要创建一个3x3的稀疏矩阵A,其中非零元素为[1, 2, 3],对应的行索引为[1, 2, 3],列索引为[1, 2, 3]。
我们可以使用以下代码创建该稀疏矩阵:MATLABA = sparse([1, 2, 3], [1, 2, 3], [1, 2, 3], 3, 3);在上述代码中,我们首先指定元素的非零值,然后是行和列索引。
最后,我们指定了矩阵的尺寸。
第三步:访问稀疏矩阵的元素与密集矩阵一样,我们可以通过索引访问稀疏矩阵的元素。
但由于稀疏矩阵中存在大量的零元素,当我们访问这些零元素时,MATLAB不会返回它们。
相反,它只返回非零元素的值。
例如,我们可以使用以下代码访问稀疏矩阵A的(1, 1)位置上的元素:MATLABelement = A(1, 1);通过这个例子,我们可以看到元素A(1, 1)的值为1。
第四步:操作稀疏矩阵与密集矩阵一样,我们可以对稀疏矩阵执行各种数学和统计操作。
MATLAB提供了许多函数和工具,可用于对稀疏矩阵执行这些操作。
例如,我们可以使用以下代码计算稀疏矩阵A的行和:MATLABrowSum = sum(A, 2);在上述代码中,'sum'函数的第二个参数设置为2,以指定我们要计算的是每一行的和。
matlab稀疏矩阵

matlab稀疏矩阵简介:稀疏矩阵是一类常见的、具有应用价值的数据结构,经常出现在科学计算和数值分析中。
MATLAB提供了丰富的函数和工具用于构建、表达和操作稀疏矩阵。
本文将介绍稀疏矩阵的定义、MATLAB 的稀疏矩阵支持函数以及稀疏矩阵的应用。
一、稀疏矩阵的定义稀疏矩阵指的是其中大部分元素的值都为零的大型矩阵,其中只有少数几个元素的值不为零。
由于稀疏矩阵中的元素很少,因此传统的矩阵存储方法就显得非常不合适了。
为了支持稀疏矩阵,需要使用特殊的存储方法来存储和运算稀疏矩阵。
二、MATLAB的稀疏矩阵支持函数MATLAB提供了稀疏矩阵支持函数,以快速高效的方式处理稀疏矩阵。
下面将介绍一些常用的稀疏矩阵支持函数:(1)构建稀疏矩阵:sparse函数:此函数可以根据稀疏数组的下标值和数据来构建稀疏矩阵。
spdiags函数:此函数可以根据边矩阵和主对角矩阵的数据来构建稀疏矩阵。
speye函数:此函数以对角线元素为1,其余元素为0的矩阵为特征来构建稀疏矩阵。
(2)表达稀疏矩阵:full函数:此函数可以将稀疏矩阵转换成一个普通的矩阵,即将稀疏矩阵中的零元素转为该矩阵的真实元素值。
find函数:此函数可以查找稀疏矩阵中满足特定条件的元素下标,以及该元素的值。
(3)操作稀疏矩阵:add函数:此函数可以将多个稀疏矩阵相加,但这些稀疏矩阵必须具有相同的大小和形状。
mtimes函数:此函数可以将两个稀疏矩阵相乘,但其大小必须相符。
rref函数:此函数可以对稀疏矩阵进行高斯消元求解,以解决方程组或最小二乘问题等问题。
三、稀疏矩阵的应用稀疏矩阵在科学计算和数值分析中有着重要的应用。
常见的应用包括:(1)线性代数:稀疏矩阵可以用于处理稀疏的线性方程组,如求解特征值问题,最小二乘问题等。
(2)机器学习:稀疏矩阵可以用于处理文本中的词语及其出现的频率,它也可以用于图像的表达和分析,因此有着广泛的应用,比如文本分类和图像识别等。
(3)图论:稀疏矩阵可以用于处理含有大量边的图形,如表示有向图、无向图或有权图等。
matlab稀疏矩阵

matlab稀疏矩阵Matlab是一款功能强大的数学计算软件,给用户提供了多种数学功能,其中稀疏矩阵的功能受到众多用户的欢迎。
本文将重点介绍Matlab在稀疏矩阵处理方面的功能及其应用。
一、什么是稀疏矩阵稀疏矩阵是指元素值的绝大部分是零的矩阵,也就是说,稀疏矩阵的元素值分布非常不均匀,非零元素较少,而零元素则较多。
同时,稀疏矩阵还有另一个特点,那就是非零元素在矩阵中呈现明显的规律,在宽度和高度上,非零元素呈现出一定的规律,这也给Matlab稀疏矩阵处理带来了巨大的便利。
二、Matlab的稀疏矩阵处理1、稀疏矩阵的创建Matlab提供了一系列实用的函数,可以帮助用户快速创建稀疏矩阵。
例如,用户可以用“sprand”函数生成稀疏矩阵,其调用方式为“A = sprand(m,n,density)”,其中m、n分别表示矩阵的行数和列数,density表示非零元素数目占总元素数目的比例。
2、稀疏矩阵的操作Matlab提供了一系列实用的函数,可以方便地对稀疏矩阵进行加减乘除等操作,例如,采用“plus”函数可以求解两个稀疏矩阵的和,其调用方式为“C = A + B”。
此外,用户还可以使用“nnz”函数求取稀疏矩阵中非零元素的数量,其调用方式为“nnz(A)”。
三、稀疏矩阵的应用1、生物学在生物学应用中,稀疏矩阵可以用来处理高维空间中的数据,可以有效解决复杂网络中的数据可视化问题。
例如,研究人员可以从生物学数据中提取稀疏矩阵,然后用Matlab处理这些稀疏矩阵,以求取研究结果。
2、信号处理稀疏矩阵也可以用于信号处理应用,用户可以用稀疏矩阵来处理图像、视频等信号数据。
例如,使用Matlab的稀疏矩阵方法处理图像,可以有效滤除噪声,提高图像质量。
3、金融稀疏矩阵在金融应用中也有着广泛的用途,可以用来处理大量金融数据。
Matlab有一个专门用于处理金融数据的Toolbox,用户可以用里面的函数来处理金融数据,以获得准确的结果。
python稀疏矩阵奇异值分解

一、概述在计算机科学领域中,稀疏矩阵是一种特殊的矩阵结构,它在现实世界的许多问题中都有着重要的应用。
而奇异值分解(Singular Value Dposition, SVD)则是一种常用的矩阵分解方法,可以用于降维、推荐系统、数据压缩等领域。
Python作为一种流行的编程语言,在处理稀疏矩阵和进行奇异值分解时发挥着重要的作用。
本文将重点介绍Python在稀疏矩阵奇异值分解方面的应用。
二、稀疏矩阵的概念与特点1. 稀疏矩阵是指绝大部分元素为零的矩阵。
在实际问题中,很多数据都具有稀疏性,比如用户-物品评分矩阵、文本数据的词频矩阵等。
2. 稀疏矩阵的特点包括存储空间大大节省、计算效率较高等。
然而,由于稀疏矩阵中零元素过多,传统的矩阵运算方法并不适用,因此需要特殊的处理方式。
三、Python中的稀疏矩阵表示与操作1. Python中有多种表示稀疏矩阵的方式,比如传统的嵌套列表、稀疏矩阵库(如scipy.sparse)等。
这些方法各有优缺点,可以根据具体情况选择合适的表示方式。
2. 在进行稀疏矩阵运算时,Python提供了丰富的库和工具,比如NumPy、SciPy等。
这些库中提供了很多高效的稀疏矩阵运算方法,可以大大提高计算效率。
四、稀疏矩阵奇异值分解的原理与方法1. 奇异值分解是一种重要的矩阵分解方法,可以将一个矩阵分解为三个矩阵的乘积。
在稀疏矩阵中,奇异值分解可以用于降维、去噪、推荐系统等领域。
2. 在Python中,可以使用SciPy库中的sparse.linalg.svds方法来对稀疏矩阵进行奇异值分解。
这个方法可以高效地处理大规模稀疏矩阵,并且支持指定分解后保留的奇异值数量。
五、实例分析:基于Python的稀疏矩阵奇异值分解应用1. 在实际应用中,我们可以利用Python进行稀疏矩阵奇异值分解,并结合其他方法进行推荐系统的构建。
比如可以使用MovieLens数据集构建用户-电影评分矩阵进行分解,从而实现电影推荐功能。
稀疏矩阵的压缩存储方法与应用场景

稀疏矩阵的压缩存储方法与应用场景稀疏矩阵指的是矩阵中绝大部分元素为0的情况下,只保存非零元素及其对应的坐标的一种存储方式。
相比于一般的矩阵存储方式,稀疏矩阵的压缩存储方法可以有效节省存储空间,并提高运算效率。
本文将介绍一些常见的稀疏矩阵的压缩存储方法以及其应用场景。
一、行压缩存储法(CRS)行压缩存储法(CRS,Compressed Row Storage)是一种经典的稀疏矩阵压缩存储方法。
在CRS中,矩阵的非零元素按行优先的顺序存储,并记录每行非零元素的开始位置及其列号。
由于CRS只存储非零元素及其对应的行列坐标,因此可以大大减少存储空间。
CRS适用于行操作较多的场景,比如图像处理、有限元分析等。
在这些场景下,常常需要对稀疏矩阵进行行操作,例如行相加、行相减、行乘以常数等。
CRS可以通过迅速定位非零元素所在的行并对其进行操作,提高计算效率。
二、列压缩存储法(CCS)列压缩存储法(CCS,Compressed Column Storage)是另一种常见的稀疏矩阵压缩存储方法。
在CCS中,矩阵的非零元素按列优先的顺序存储,并记录每列非零元素的开始位置及其行号。
与CRS相比,CCS可以更加高效地进行列操作,如列相加、列相减、列乘以常数等。
CCS常用于图论、网络分析等领域。
例如,在图论中,常常需要对邻接矩阵进行列操作,如计算图的邻接节点、计算图的度数等。
CCS 可以快速对非零元素所在的列进行操作,提高计算效率。
三、对角线压缩存储法(Diagonal Storage)对角线压缩存储法是一种适用于具有特殊结构的稀疏矩阵的压缩存储方法。
在对角线压缩存储法中,只存储矩阵的非零主对角线元素以及非零副对角线元素,其余元素均为0。
通过存储非零对角线元素及其位置,可以进一步减少存储空间。
对角线压缩存储法适用于具有对称或反对称性质的矩阵。
在数值计算、网络传输等领域,经常需要处理对称或反对称矩阵。
对角线压缩存储法可以有效存储这类特殊结构的矩阵,并提高运算效率。
大型稀疏矩阵的优化压缩存储技术及其应用

大型稀疏矩阵的优化压缩存储技术及其应用
随着科技的不断发展和应用,大型稀疏矩阵的应用逐渐增加。
然而,大型稀疏矩阵在存储时会占用大量的空间,导致存储和计算成本高。
因此,如何优化大型稀疏矩阵的存储是一个需要解决的问题。
优化稀疏矩阵存储的常见方法是稀疏矩阵压缩存储技术,该技术
可以通过将矩阵中的零元素进行压缩,从而降低存储空间。
现在,主
要有三种存储格式:COO格式、CSR格式以及CSC格式。
COO格式是最简单的稀疏矩阵压缩格式,它把非零元素的行列坐
标和对应的数值存储在一个三元组中。
COO格式具有灵活性和简单性,但是由于存在大量的重复行和列,会浪费大量的存储空间。
CSR格式和CSC格式是针对COO格式的优化,它们分别按照行和
列的顺序存储矩阵的非零元素,并记录每行或每列非零元素的个数和
起始位置。
这种方式比COO格式更加高效,可以大幅度减少存储空间。
然而,这两种格式的存储方法都有一定的局限性,因此现在还有其他
一些稀疏矩阵存储格式,如LIL,JDS等。
大型稀疏矩阵优化压缩存储技术的应用范围非常广泛,如科学计算、图谱算法、机器学习等都有它的应用。
例如,在机器学习中,稀
疏矩阵存储格式可以用来存储大型的文本数据和特征向量,以便进行
文本挖掘和分类等任务。
同时,它还可以被用于处理搜索引擎、社交
网络和图像识别等领域的数据。
总之,大型稀疏矩阵的优化压缩存储技术是十分重要的技术,可
以大幅度降低存储和计算成本,同时提高速度和效率。
随着科技的不
断发展和应用,这一技术将会在更多的领域得到应用。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
稀疏矩阵应用●课题简介1.1课题及要求稀疏矩阵应用(限1 人完成)设计要求:实现三元组,十字链表下的稀疏矩阵的加、转、乘的实现。
(1)稀疏矩阵的存储(2)稀疏矩阵加法(3)矩阵乘法(4)矩阵转置1.2课程任务分析本课程设计主要实现在三元组存储结构与十字链表存储结构下输入稀疏矩阵,并对稀疏矩阵进行转置,相加,相乘操作,最后输出运算后的结果。
稀疏矩阵采用三元组和十字链表表示,并在两种不同的存储结构下,求两个具有相同行列数的稀疏矩阵A和B的相加矩阵C,并输出C;求出A的转置矩阵D,输出D;求两个稀疏矩阵A和B的相乘矩阵E,并输出E。
1.3课程的意义其意义是让我们在学习完C、数据结构等课程基础上,掌握多维数组的逻辑结构和存储结构、掌握稀疏矩阵的压缩存储及转置,相加,相乘等基本操作,并用不同的方法输出结果,进一步掌握设计、实现较大系统的完整过程,包括系统分析、编码设计、系统集成、以及调试分析,熟练掌握数据结构的选择、设计、实现以及操作方法,为进一步的应用开发打好基础。
●程序分析2.1设计函数建立稀疏矩阵及初始化值和输出稀疏矩阵的值本模块要求设计函数建立稀疏矩阵并初始化,包括在三元组结构下和十字链表结构下。
首先要定义两种不同的结构体类型,在创建稀疏矩阵时,需要设计两个不同的函数分别在三元组和十字链表下创建稀疏矩阵,在输入出现错误时,能够对错误进行判别处理,初始化稀疏矩阵都为空值,特别注意在十字链表下,对变量进行动态的地址分配。
在设计输出稀疏矩阵的值的函数时,也要针对两种不同的情况,分别编制函数,才能准确的输出稀疏矩阵。
在对稀疏矩阵进行初始化及输出值时,均只输出非零元素的值和它所在的所在行及所在列。
2.2构造函数进行稀疏矩阵的转置并输出结果本模块要求设计函数进行稀疏矩阵的转置并输出转置后的结果,由于对稀疏函数的转置只对一个矩阵进行操作,所以实现起来难度不是很大,函数也比较容易编写。
在编写函数时,要先定义一个相应的结构体变量用于存放转置后的矩阵,最后把此矩阵输出。
2.3构造函数进行两个稀疏矩阵相加及相乘并输出最终的稀疏矩阵本模块要求设计相加和相乘函数对两个矩阵进行运算,并输出最终的稀疏矩阵,在进行运算前,要对两个矩阵进行检查,看是不是相同类型的矩阵,因为两个矩阵相加要求两个矩阵一定是同一类型的矩阵,定义相应的矩阵类型用于存放两个矩阵相加相乘后的结果矩阵,这个结果矩阵的行数列数需要综合多方面情况来确定。
这四个函数也是整个程序的难点,需要灵活运用数组及指针的特点。
2.4退出系统本模块要求设置选项能随时结束程序的运行,本程序中采用exit(0)函数。
程序以用户和计算机的对话方式执行,即在计算机终端上显示“提示信息”之后,由用户在键盘上输入演示程序中需要的相关信息及命令。
概要设计3.1主界面设计为了实现在两种存储结构下对稀疏矩阵的多种算法功能的管理,首先设计一含有多个菜单项的主控菜单子程序以链接系统的各项子功能,方便用户交互式使用本系统。
本系统主控菜单运行界面如图1所示。
图1主界面图3.2存储结构设计本系统采用三元组结构和十字链表结构存储稀疏矩阵的具体信息。
其中:在三元组中,所有元素的信息用数组表示,每个数组元素中包含有行下标(i),列下标(j)和对应的数值(e),它们是整型数据,全部的信息用在十字链表中,全部结点的信息用结构体(TSMatrix)包含,包括用数组(Triple data[MAXSIZE])和总共的行数(mu),列数(nu)以及非零元素的个数(tu)。
在十字链表下,头结点为指针数组的十字链表存储;每个结点里面包含行下标(i),列下标(j)和对应的数值(e),它们是整型数据,还有两个指针(right)、(down),属于OLNode结构体。
全部的信息用结构体(crosslist)包含,包括指针数组(OLink* rhead和*chead)和总共的行数(mu),列数(nu)以及非零元素的个数(tu)。
三元组结构体定义:typedef struct{int i,j;int e;}Triple;typedef struct{Triple data[MAXSIZE];int rpos[MAXSIZE + 1];int nu,mu,tu;}TSMatrix;十字链表结构体定义:typedef struct OLNode{int i,j;int e;struct OLNode *right,*down;}OLNode,*OLink;typedef struct {int mu,nu,tu;OLink *rhead,*chead;}CrossList;3.3系统功能设计本系统除了要完成分别在三元组存储结构以及在十字链表下实现稀疏矩阵的初始化功能外还设置了4个子功能菜单。
稀疏矩阵的建立及初始化在三元组存储结构下,由函数voidCreateSMatrix(TSMatrix&M)实现,在十字链表存储结构下,由函数void CreateSMatix_OL(CrossList&M)依据读入的行数和列数以及非零元素的个数,分别设定每个非零元素的信息。
4个子功能的设计描述如下。
(1)稀疏矩阵的转置:此功能在三元组存储结构下,由函数void TransposeSMatrix(TSMatrix M,TSMatrix &T)实现,在十字链表存储结构下,由函数void TurnSMatrix_OL(CrossList &M)实现。
当用户选择该功能,系统提示用户初始化一个矩阵,然后进行转置,最终输出结果。
(2)稀疏矩阵的加法:此功能在三元组存储结构下,由函数void AddTMatix(TSMatrix M,TSMatrix T,TSMatrix &S)实现,在十字链表存储结构下,由函数int SMatrix_ADD(CrossList *A,CrossList *B)实现。
当用户选择该功能,系统即提示用户初始化要进行加法的两个矩阵的信息。
然后进行加法,最后输出结果。
(3)稀疏矩阵的乘法:此功能在三元组存储结构下,由函数int MultSMatrix(TSMatrix M, TSMatrix N, TSMatrix &Q)实现。
在十字链表存储结构下,由函数int MultSMatrix_OL(CrossList M, CrossList N, CrossList &Q)实现。
当用户选择该功能,系统提示输入要进行相乘的两个矩阵的详细信息。
然后进行相乘,最后得到结果。
(4)退出:即退出稀疏矩阵的应用系统,由exit(0)函数实现。
当用户选择该功能,则退出该稀疏矩阵的应用系统。
调试分析4.1系统运行主界面系统运行主界面如图2所示:图2 主界面图4.2 各子功能测试运行结果(以三元组为例)(1)稀疏矩阵的创建及初始化:在主菜单下,用户输入1回车,是用三元组创建稀疏矩阵,根据屏幕提示初始化一个稀疏矩阵,按enter键,运行结果如图3所示。
图3 三元组创建并初始化矩阵(2)稀疏矩阵的转置:用三元组创建稀疏矩阵后,用户输入1回车,便显示该矩阵的转置矩阵,运行结果如图4所示。
图4 三元组稀疏矩阵转置结果示意图(3)稀疏矩阵的相加:用三元组创建并初始化一个稀疏矩阵后,输入2回车,按屏幕提示输入第二个同类型的稀疏矩阵,按enter键,运行结果如图5所示。
图5 三元组稀疏矩阵相加结果示意图(4)稀疏矩阵的相乘:用三元组创建并初始化一个稀疏矩阵后,输入3回车,按屏幕提示输入第二个同类型的稀疏矩阵,按enter键,运行结果如图6所示。
图6三元组稀疏矩阵相乘结果示意图(5)退出:在主菜单下,用户输入3回车,或者在下级菜单中输入4回车,退出程序。
运行结果如图7,图8。
图7 主菜单退出程序图图8 下级菜单退出程序图总结由于本程序要求用两种办法对稀疏矩阵进行运算,特别是用十字链表这种形式来对稀疏矩阵进行运算,是实现起来有很多困难,主要包括:1、书上这种方面的东西不多,资料少,可以参考的东西不是很多;2、用十字链表进行运算比较复杂,难度较大,需要对指针掌握较好;3、在书写课程设计报告时,没有具体的模板,感觉无从下手。
针对上述困难,我通过网络,图书馆找资料,借鉴别人的以往的优秀的课程设计报告,和同学们一起讨论,逐步地解决自己的问题。
通过此次课程设计,使我对本学期学的《数据结构》有了更深的了解,也使自己的所学更加牢固,并能够把更方面的知识综合起来运用。
附录:程序源代码#include<stdio.h>#include<stdlib.h>#define MAXSIZE 100int num[100];typedef struct OLNode{int i,j;int e;struct OLNode *right,*down;}OLNode,*OLink;typedef struct {int mu,nu,tu;OLink *rhead,*chead;}CrossList; //十字链表结构体定义typedef struct{int i,j;int e;}Triple;typedef struct{Triple data[MAXSIZE];int rpos[MAXSIZE + 1];int nu,mu,tu;}TSMatrix; //三元组结构体定义;int CreateSMatix_OL(CrossList &M){int i,j,e;OLink q;OLink p;printf("请输入稀疏矩阵的行数,列数,非零元素的个数:"); //矩阵行数,列数下标均从开始;scanf("%d%d%d",&M.mu,&M.nu,&M.tu);M.rhead=(OLink *)malloc((M.mu+1)*sizeof(OLNode));//分配内存空间M.chead=(OLink *)malloc((M.nu+1)*sizeof(OLNode));//分配内存空间for( i=1;i<=M.mu;i++)M.rhead[i]=NULL;//把矩阵每个元素置空值for( i=1;i<=M.nu;i++)M.chead[i]=NULL;printf("请输入稀疏矩阵,如果行为0,则退出\n");scanf("%d%d%d",&i,&j,&e);while(i!=0){p=(OLink)malloc(sizeof(OLNode));p->i=i;p->j=j;p->e=e;if(M.rhead[i]==NULL||M.rhead[i]->j>j){p->right=M.rhead[i];M.rhead[i]=p;}else{q=M.rhead[i];while(q->right&&q->right->j<j)q=q->right;p->right=q->right;q->right=p;}if(M.chead[j]==NULL||M.chead[j]->i>i){p->down=M.chead[j];M.chead[j]=p;}else{q=M.chead[j];while(q->down&&q->down->i<i)q=q->down;p->down=q->down;q->down=p;}scanf("%d%d%d",&i,&j,&e);}return 1;}//创建十字链表void CreateSMatrix(TSMatrix &M){//采用三元组顺序表存储表示,创建稀疏矩阵Mprintf("请输入稀疏矩阵的行数、列数和非零元个数:");scanf("%d%d%d",&M.mu,&M.nu,&M.tu);if((M.mu<=0)||(M.nu<=0)||(M.tu<=0)||(M.tu>M.mu*M.nu))//判断行值、列值、元素个数是否合法printf("输入有误!");for(int i=1;i<=M.tu;i++){//输入稀疏矩阵元素printf("请输入元素坐标(所在行,所在列)及大小:");scanf("%d%d%d",&M.data[i].i,&M.data[i].j,&M.data[i].e);if((M.data[i].i<=0)||(M.data[i].j<=0)){printf("输入错误,请重新输入");scanf("%d%d%d",&M.data[i].i,&M.data[i].j,&M.data[i].e);}//if}//for iint num[100];if(M.tu){int i;for(i = 1; i <= M.mu; i++) num[i] = 0;//初始化for(int t = 1; t <= M.tu; t++) ++num[M.data[t].i];//求M中每一行含非零元素个数//求rposM.rpos[1] = 1;for(i = 2; i <= M.mu; i++) M.rpos[i] = M.rpos[i-1] + num[i-1];}}//创建三元组void TransposeSMatrix(TSMatrix M,TSMatrix &T){T.nu=M.mu;//T矩阵存放转置后的矩阵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;}void AddTMatix(TSMatrix M,TSMatrix T,TSMatrix &S){//矩阵S存放相加后的矩阵S.mu=M.mu>T.mu?M.mu:T.mu;//对S矩阵的行数赋值S.nu=M.nu>T.nu?M.nu:T.nu;//对S矩阵的列数赋值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)) //用switch分支语句,用compare函数对需要相加的两个矩阵的某元素行数列数进行比较{case -1: S.data[q].e=M.data[mcount].e;//当M.data[mcount].i<T.data[tcount].i或M.data[mcount].j<T.data[tcount].jS.data[q].i=M.data[mcount].i;S.data[q].j=M.data[mcount].j;//把第一个矩阵的行数i,列数j赋值给S矩阵的行数i,列数jq++;mcount++;break;case 1: S.data[q].e=T.data[tcount].e;//当M.data[mcount].i>T.data[tcount].i或M.data[mcount].j>T.data[tcount].jS.data[q].i=T.data[tcount].i;S.data[q].j=T.data[tcount].j;//把第二个矩阵的行数i,列数j赋值给S矩阵的行数i,列数jq++;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++; }//在case=-1的情况下对S矩阵的非零值,行数,列数进行赋值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++;}//在case=1的情况下对S矩阵的非零值,行数,列数进行赋值S.tu=q-1;}//三元组相加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;//三元组结构类型Q存放相乘后的结果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) //把运算后的结果存放到Q中{ 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;}//三元组相乘void ShowTMatrix(TSMatrix M){for(int col=1;col<=M.mu;col++)//通过双重循环,把稀疏矩阵中不为零的元素的行数、列数和值显示出来for(int p=1;p<=M.tu;p++)if(M.data[p].i==col)printf("%4d %4d %4d\n",M.data[p].i,M.data[p].j,M.data[p].e);}//三元组显示void TurnSMatrix_OL(CrossList &M){int col,row; //定义循环变量OLink p,q; //定义OLink结构类型变量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;}}}//十字链表转置int SMatrix_ADD(CrossList *A,CrossList *B){OLNode *pa,*pb,*pre,*p,*cp[100]; //定义OLNode类型的变量int i,j,t;t=A->tu+B->tu;for(j=1;j<=A->nu;j++)cp[j]=A->chead[j];//将A矩阵的列表头指针赋给cp数组for(i=1;i<=A->mu;i++){pa=A->rhead[i];pb=B->rhead[i];//将A,B矩阵的行表头指针分别赋给pa,pbpre=NULL;while(pb){//当pb不等于零if(pa==NULL||pa->j>pb->j){p=(OLink)malloc(sizeof(OLNode));//给p动态分配空间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;}//如果A->chead[p->j]不等于零,则把p赋给它及cp[p->j]else{cp[p->j]->down=p;cp[p->j]=p;}pb=pb->right;}//否则把p赋给cp[p->j]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;//A的行与列为A及B当中较大的一个return 1;}//十字链表相加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的行数不相等,不能相乘。