稀疏矩阵的存储及运算

合集下载

稀疏矩阵的三元组顺序表存储表示及其转置算法

稀疏矩阵的三元组顺序表存储表示及其转置算法

稀疏矩阵的三元组顺序表存储表示及其转置算法目录1. 引言1.1 背景和意义1.2 结构概述1.3 目的2. 稀疏矩阵的三元组顺序表存储表示2.1 稀疏矩阵的定义与特点2.2 三元组顺序表的数据结构和实现方式2.3 存储表示的优缺点分析3. 稀疏矩阵转置算法3.1 转置操作的意义与应用场景3.2 基于三元组顺序表的转置算法设计思路3.3 转置算法的具体实现步骤与复杂度分析4. 实验与结果分析4.1 实验设置和数据样本介绍4.2 转置算法在不同稀疏矩阵上的性能评估和结果比较4.3 分析结果及启示与讨论5. 结论与展望5.1 结论总结5.2 存在问题及后续工作展望1. 引言1.1 背景和意义稀疏矩阵是一种在实际问题中经常遇到的特殊矩阵结构,其绝大部分元素为零。

与稠密矩阵相比,稀疏矩阵的存储和计算效率更高。

稀疏矩阵可以应用于图像处理、网络分析、线性代数等领域。

三元组顺序表是一种存储稀疏矩阵的数据结构,通过记录非零元素的行索引、列索引和数值,有效地减少了存储空间。

同时,三元组顺序表也提供了便捷的转置操作方式。

因此,深入掌握稀疏矩阵的三元组顺序表存储表示及其转置算法对于提高稀疏矩阵相关问题的解决效率具有重要意义。

1.2 结构概述本文将从两个方面进行论述。

首先,介绍稀疏矩阵的定义与特点,以及三元组顺序表在存储表示中所采用的数据结构和实现方式。

其次,详细描述了基于三元组顺序表的稀疏矩阵转置算法的设计思路、具体实现步骤和复杂度分析。

1.3 目的本文旨在探究稀疏矩阵的三元组顺序表存储表示及其转置算法,在理论层面上深入分析其原理和优劣,并在实验中验证其性能表现。

通过本文的研究,我们希望能够提供一种高效、灵活且易于实现的方法来处理稀疏矩阵,并为进一步的相关应用提供有价值的启示和参考。

2. 稀疏矩阵的三元组顺序表存储表示2.1 稀疏矩阵的定义与特点稀疏矩阵是指在一个二维矩阵中,大部分元素都为0的情况下,只有少数非零元素的情况。

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

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

数据结构之稀疏矩阵稀疏矩阵的存储方式和操作分析稀疏矩阵是指矩阵中大部分元素为零的特殊矩阵。

在实际应用中,稀疏矩阵经常出现,如图像处理、网络分析和科学计算等领域。

对于稀疏矩阵的存储和操作是数据结构中的重要内容。

本文将介绍稀疏矩阵的存储方式和相关操作的分析。

一、稀疏矩阵存储方式稀疏矩阵的存储方式有多种,其中三元组顺序表和二维数组是比较常用的方法。

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的矩阵,而只有少数元素非零。

在实际应用中,许多矩阵都具有这种稀疏性质,例如语言模型中的词频矩阵、推荐系统中的用户评分矩阵等。

由于稀疏矩阵中大部分元素为0,传统的存储方式会造成大量空间的浪费。

因此,存储稀疏矩阵成为了一个重要的问题。

为了高效地存储稀疏矩阵,可以采用压缩存储的方法。

常见的压缩存储方法有三种:行压缩存储(CSR)、列压缩存储(CSC)和坐标列表(COO)。

行压缩存储(CSR)是一种按行存储稀疏矩阵的方法。

它使用三个数组来表示稀疏矩阵:data、indices和indptr。

其中,data数组存储非零元素的值,indices数组存储非零元素所在的列索引,indptr数组存储每一行的起始位置。

通过这种方式,可以有效地存储稀疏矩阵,并且可以方便地进行矩阵乘法等操作。

列压缩存储(CSC)与行压缩存储类似,只是它按列存储稀疏矩阵。

CSC使用三个数组来表示稀疏矩阵:data、indices和indptr。

其中,data数组存储非零元素的值,indices数组存储非零元素所在的行索引,indptr数组存储每一列的起始位置。

通过CSC存储方式,可以方便地进行矩阵转置等操作。

坐标列表(COO)是一种简单直观的稀疏矩阵存储方式。

COO使用三个数组来表示稀疏矩阵:row、col和data。

其中,row数组存储非零元素所在的行索引,col数组存储非零元素所在的列索引,data 数组存储非零元素的值。

COO存储方式适合于构建稀疏矩阵,但不适合进行矩阵操作。

除了上述三种常见的压缩存储方法外,还有一些其他的存储方式。

例如,对于二维稀疏矩阵,可以使用四叉树存储方式。

四叉树将矩阵划分为四个象限,每个象限再递归地进行划分,直到划分到某个节点中只有一个非零元素为止。

这种存储方式能够高效地存储稀疏矩阵,并且可以方便地进行矩阵操作。

在实际应用中,根据具体的需求和矩阵的特点,选择合适的存储方式非常重要。

稀疏矩阵的压缩存储方法及主要运算的实现

稀疏矩阵的压缩存储方法及主要运算的实现

1.实验目的:掌握稀疏矩阵的压缩存储方法及主要运算的实现。

2.实验内容与要求:设计一个稀疏矩阵计算器,要求能够:⑴输入并建立稀疏矩阵;⑵输出稀疏矩阵;⑶执行两个矩阵相加;⑷执行两个矩阵相乘;⑸求一个矩阵的转置矩阵。

3.数据结构设计逻辑结构:线性结构存储结构:顺序存储结构4.算法设计#include<stdio.h>#define MAXSIZE 100typedef int datatype;typedef struct{ int i,j;datatype v;}Triple;typedef struct{ Triple data[MAXSIZE+1];int rpos[MAXSIZE+1];int mu,nu,tu;}RLSMatrix;int main(){ void AddSMatrix(RLSMatrix M);void MultSMatrix(RLSMatrix M);void FastTransposeSMatrix(RLSMatrix M);RLSMatrix M;int k;printf("请输入稀疏矩阵M的行数、列数和非零元素个数:");scanf("%d%d%d",&M.mu,&M.nu,&M.tu);printf("请输入稀疏矩阵M中非零元素的行号、列号和元素的值:\n");for(k=1;k<=M.tu;k++)scanf("%d%d%d",&M.data[k].i,&M.data[k].j,&M.data[k].v);printf("请输出稀疏矩阵M中非零元素的行号、列号和元素的值:\n");for(k=1;k<=M.tu;k++){ printf("%d%3d%3d",M.data[k].i,M.data[k].j,M.data[k].v);printf("\n");}AddSMatrix(M);MultSMatrix(M);FastTransposeSMatrix(M);return 0;}void AddSMatrix(RLSMatrix M){ RLSMatrix N,R;int k,l=1,s=1;printf("请输入稀疏矩阵N的行数、列数和非零元素个数:");scanf("%d%d%d",&N.mu,&N.nu,&N.tu);printf("请输入稀疏矩阵N中非零元素的行号、列号和元素的值:\n"); for(k=1;k<=N.tu;k++)scanf("%d%d%d",&N.data[k].i,&N.data[k].j,&N.data[k].v);if(M.mu!=N.mu||M.nu!=N.nu) printf("错误\n");else{ R.mu=M.mu;R.nu=M.nu;k=1;if(M.tu*N.tu!=0){ while(k<=M.tu&&l<=N.tu){ if(M.data[k].i==N.data[l].i){ if(M.data[k].j<N.data[k].j){ R.data[s].i=M.data[k].i;R.data[s].j=M.data[k].j;R.data[s].v=M.data[k].v;k++;s++;}else if(M.data[k].j==N.data[l].j){ R.data[s].i=M.data[k].i;R.data[s].j=M.data[k].j;R.data[s].v=M.data[k].v+N.data[l].v;if(R.data[s].v!=0) s++;k++;l++;}else{ R.data[s].i=N.data[l].i;R.data[s].j=N.data[l].j;R.data[s].v=N.data[l].v;l++;s++;}}else if(M.data[k].i<N.data[l].i){ R.data[s].i=M.data[k].i;R.data[s].j=M.data[k].j;R.data[s].v=M.data[k].v;k++;s++;}else{ R.data[s].i=N.data[l].i;R.data[s].j=N.data[l].j;R.data[s].v=N.data[l].v;l++;s++;}}while(k<=M.tu){ R.data[s].i=M.data[k].i;R.data[s].j=M.data[k].j;R.data[s].v=M.data[k].v;k++;s++;}while(l<=N.tu){ R.data[s].i=N.data[l].i;R.data[s].j=N.data[l].j;R.data[s].v=N.data[l].v;l++;s++;}}printf("请输出稀疏矩阵M和稀疏矩阵N的和矩阵R中非零元素的行号、列号和元素的值:\n");for(k=1;k<s;k++)printf("%d%3d%3d\n",R.data[k].i,R.data[k].j,R.data[k].v);}}void MultSMatrix(RLSMatrix M){ RLSMatrix D,Q;int num1[MAXSIZE],num2[MAXSIZE],ctemp[MAXSIZE],arow,brow,ccol,p,q,tp,t; printf("请输入稀疏矩阵D的行数、列数和非零元素个数:");scanf("%d%d%d",&D.mu,&D.nu,&D.tu);printf("请输入稀疏矩阵D中非零元素的行号、列号和元素的值:\n");for(t=1;t<=D.tu;t++)scanf("%d%d%d",&D.data[t].i,&D.data[t].j,&D.data[t].v);for(ccol=1;ccol<=M.mu;ccol++)num1[ccol]=0;for(t=1;t<=M.tu;t++)num1[M.data[t].i]++;M.rpos[1]=1;for(ccol=2;ccol<=M.mu;ccol++)M.rpos[ccol]=M.rpos[ccol-1]+num1[ccol-1];for(ccol=1;ccol<=D.mu;ccol++)num2[ccol]=0;for(t=1;t<=D.tu;t++)num2[D.data[t].i]++;D.rpos[1]=1;for(ccol=2;ccol<=D.mu;ccol++)D.rpos[ccol]=D.rpos[ccol-1]+num2[ccol-1];if(M.nu!=D.mu) printf("错误\n");else{ Q.mu=M.mu;Q.nu=D.nu;Q.tu=0;if(M.tu*D.tu!=0){ for(arow=1;arow<=M.mu;arow++){ for(ccol=1;ccol<=Q.nu;ccol++)ctemp[ccol]=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<D.mu) t=D.rpos[brow+1];else t=D.tu+1;for(q=D.rpos[brow];q<t;q++){ ccol=D.data[q].j;ctemp[ccol]+=M.data[p].v*D.data[q].v;}}for(ccol=1;ccol<=Q.nu;ccol++)if(ctemp[ccol]!=0){ if(++Q.tu>MAXSIZE) printf("错误\n");else{ Q.data[Q.tu].i=arow;Q.data[Q.tu].j=ccol;Q.data[Q.tu].v=ctemp[ccol];}}}}}printf("请输出稀疏矩阵M和稀疏矩阵D的乘积矩阵Q中非零元素的行号、列号和元素的值:\n");for(ccol=1;ccol<=Q.tu;ccol++)printf("%d%3d%3d\n",Q.data[ccol].i,Q.data[ccol].j,Q.data[ccol].v);}void FastTransposeSMatrix(RLSMatrix M){ RLSMatrix T;int num[MAXSIZE],cpot[MAXSIZE],col,p,q,t;T.mu=M.mu;T.nu=M.nu;T.tu=M.tu;if(T.tu!=0){ for(col=1;col<=M.mu;col++)num[col]=0;for(t=1;t<=M.tu;t++)num[M.data[t].j]++;cpot[1]=1;for(col=2;col<=M.nu;col++)cpot[col]=cpot[col-1]+num[col-1];for(p=1;p<=M.tu;p++){ col=M.data[p].j;q=cpot[col];T.data[q].i=M.data[p].j;T.data[q].j=M.data[p].i;T.data[q].v=M.data[p].v;cpot[col]++;}}printf("请输出将稀疏矩阵M转置后的稀疏矩阵T中非零元素的行号、列号和元素的值:\n");for(col=1;col<=T.tu;col++)printf("%d%3d%3d\n",T.data[col].i,T.data[col].j,T.data[col].v);}。

稀疏矩阵加法乘法

稀疏矩阵加法乘法

稀疏矩阵加法乘法稀疏矩阵是指其中大部分元素都是0的矩阵,而只有极小部分元素为非0值。

与密集矩阵相比,稀疏矩阵具有更高的压缩率以及更快的计算速度,因此在大型数据处理和机器学习等领域中得到了广泛应用。

稀疏矩阵加法和乘法是稀疏矩阵计算中最基本的两个操作。

一、稀疏矩阵的表示方法基于稀疏矩阵的特殊性质,我们通常使用三元组(TUPLES)实现稀疏矩阵的存储。

三元组存储方式将一个i * j的稀疏矩阵表示为三个一维数组,分别存储非零元素的值,行坐标和列坐标。

例如,一个矩阵:1 0 00 2 00 0 3通过三元组存储方式可以表示为:value = [1, 2, 3]row = [0, 1, 2]col = [0, 1, 2]值为1的元素位于第0行第0列,值为2的元素位于第1行第1列,值为3的元素位于第2行第2列。

二、稀疏矩阵的加法两个稀疏矩阵相加的操作可以通过对两个矩阵的三元组进行合并,对于重复的元素,则将它们的值相加。

例如,对于两个矩阵A和B:A:1 0 00 2 00 0 3B:1 0 00 2 00 0 3则可以通过以下方式对A和B进行加法操作:value = [1+1, 2+2, 3+3]row = [0, 1, 2]col = [0, 1, 2]即结果矩阵为:2 0 00 4 00 0 6三、稀疏矩阵的乘法稀疏矩阵乘法的实现比较复杂,首先需要明确一点,即两个矩阵相乘的结果不一定是稀疏矩阵。

我们可以使用两种常见的算法实现稀疏矩阵的乘法:COO算法和CSR算法。

1. COO算法COO算法也称坐标格式算法,其基本思路是将两个矩阵的三元组转换成一个三元组,然后依次进行乘法运算,最后将结果累加得到最终结果的三元组。

例如,对于两个矩阵A和B:A:1 23 4B:5 67 8则可以按照以下步骤进行乘法操作:①将矩阵A表示为三元组形式:value_A = [1,2,3,4]row_A = [0,0,1,1]col_A = [0,1,0,1]②将矩阵B表示为三元组形式:value_B = [5,6,7,8]row_B = [0,0,1,1]col_B = [0,1,0,1]③对A和B的三元组进行合并得到三元组C:value_C = [1,2,3,4,5,6,7,8]row_C = [0,0,1,1,0,0,1,1]col_C = [0,1,0,1,1,0,1,0]其中row_C和col_C表示的是C中每个元素对应的行数和列数。

稀疏矩阵存储方式

稀疏矩阵存储方式

稀疏矩阵存储方式稀疏矩阵存储方式是一种优化矩阵存储的方法,它可以有效地节省内存空间并提高计算效率。

在传统的矩阵存储方式中,所有元素都被存储在一个二维数组中,无论元素是否为零。

而稀疏矩阵存储方式则只存储非零元素及其对应的行列索引,从而减少了存储空间的占用。

稀疏矩阵通常出现在一些特定的应用场景中,例如网络图、社交网络、文本处理等。

在这些场景中,矩阵往往具有大量的零元素,而非零元素只占据了很小的一部分。

如果采用传统的矩阵存储方式,会造成极大的存储空间浪费和计算效率低下。

而采用稀疏矩阵存储方式,可以大幅度地减少存储空间的占用,提高计算效率。

稀疏矩阵存储方式有多种实现方法,常见的有三元组表示法、邻接表表示法和压缩行表示法。

三元组表示法是一种简单直观的方法,它将非零元素及其对应的行列索引保存在一个三元组数组中。

邻接表表示法则是将矩阵转换为图的邻接表表示,每个非零元素都对应一个图的边。

压缩行表示法是一种更加高效的方法,它将矩阵的每一行压缩为一个一维数组,并使用两个辅助数组分别存储非零元素所在的列索引和起始位置。

稀疏矩阵存储方式的选择取决于具体的应用需求和性能要求。

三元组表示法适用于非常稀疏的矩阵,但在进行矩阵运算时效率较低。

邻接表表示法适用于稀疏度较高的矩阵,但对于稀疏度较低的矩阵效率会较低。

压缩行表示法是一种综合性能较好的方法,适用于各种稀疏度的矩阵,并且支持高效的矩阵运算。

稀疏矩阵存储方式的优势不仅在于节省存储空间,还在于提高计算效率。

由于稀疏矩阵存储方式只存储非零元素,因此在进行矩阵运算时可以忽略大量的零元素,从而减少了运算量。

此外,稀疏矩阵存储方式还可以降低缓存未命中率,提高数据访问的局部性,进一步提高计算效率。

在实际应用中,稀疏矩阵存储方式被广泛应用于各种科学计算、数据挖掘和机器学习等领域。

例如,在图像处理中,图像往往可以表示为一个巨大的稀疏矩阵。

采用稀疏矩阵存储方式可以大幅度减少存储空间的占用,并提高图像处理的速度和效果。

稀疏矩阵存储和操作稀疏矩阵的数据结构与算法

稀疏矩阵存储和操作稀疏矩阵的数据结构与算法

稀疏矩阵存储和操作稀疏矩阵的数据结构与算法稀疏矩阵是指具有大量零元素和少量非零元素的矩阵。

在实际场景中,由于矩阵中大部分元素为零,传统的矩阵存储方式会造成大量的存储空间的浪费以及数据操作的低效性。

因此,为了节省存储空间和提高数据操作的效率,稀疏矩阵的存储和操作需要借助于特定的数据结构和算法。

一、稀疏矩阵存储的数据结构1.1. 压缩存储方法压缩存储方法是一种常用的稀疏矩阵存储方法。

常见的压缩存储方法有三种:行压缩法(CSR)、列压缩法(CSC)和十字链表法。

1.1.1. 行压缩法(CSR)行压缩法是通过两个数组来存储稀疏矩阵的非零元素。

第一个数组存储非零元素的值,第二个数组存储非零元素在矩阵中的位置信息。

1.1.2. 列压缩法(CSC)列压缩法与行压缩法相似,只是存储方式不同。

列压缩法是通过两个数组来存储稀疏矩阵的非零元素。

第一个数组存储非零元素的值,第二个数组存储非零元素在矩阵中的位置信息。

1.1.3. 十字链表法十字链表法是一种更加灵活的稀疏矩阵存储方法。

通过使用链表的方式,将非零元素存储在链表中,并且每个非零元素还具有行和列的指针,方便进行数据操作。

1.2. 坐标存储法坐标存储法是一种简单直观的稀疏矩阵存储方法。

每个非零元素包括行列坐标和元素值,通过三元组的方式进行存储。

二、稀疏矩阵的操作算法2.1. 矩阵转置矩阵转置是指将原矩阵的行变为列,列变为行的操作。

对于稀疏矩阵,常用的转置算法为快速转置算法。

该算法通过统计每列非零元素的个数,并根据列的非零元素个数确定每个非零元素转置后的位置。

2.2. 矩阵相加矩阵相加是指将两个矩阵对应位置上的元素相加得到一个新的矩阵。

对于稀疏矩阵的相加,可以遍历两个矩阵的非零元素,对相同位置上的元素进行相加。

2.3. 矩阵相乘矩阵相乘是指将两个矩阵相乘得到一个新的矩阵。

对于稀疏矩阵的相乘,常用的算法为稀疏矩阵乘法算法。

该算法通过遍历两个矩阵的非零元素,按照矩阵乘法的规则计算得到新矩阵的非零元素。

稀疏矩阵的压缩存储方法与应用场景

稀疏矩阵的压缩存储方法与应用场景

稀疏矩阵的压缩存储方法与应用场景稀疏矩阵指的是矩阵中绝大部分元素为0的情况下,只保存非零元素及其对应的坐标的一种存储方式。

相比于一般的矩阵存储方式,稀疏矩阵的压缩存储方法可以有效节省存储空间,并提高运算效率。

本文将介绍一些常见的稀疏矩阵的压缩存储方法以及其应用场景。

一、行压缩存储法(CRS)行压缩存储法(CRS,Compressed Row Storage)是一种经典的稀疏矩阵压缩存储方法。

在CRS中,矩阵的非零元素按行优先的顺序存储,并记录每行非零元素的开始位置及其列号。

由于CRS只存储非零元素及其对应的行列坐标,因此可以大大减少存储空间。

CRS适用于行操作较多的场景,比如图像处理、有限元分析等。

在这些场景下,常常需要对稀疏矩阵进行行操作,例如行相加、行相减、行乘以常数等。

CRS可以通过迅速定位非零元素所在的行并对其进行操作,提高计算效率。

二、列压缩存储法(CCS)列压缩存储法(CCS,Compressed Column Storage)是另一种常见的稀疏矩阵压缩存储方法。

在CCS中,矩阵的非零元素按列优先的顺序存储,并记录每列非零元素的开始位置及其行号。

与CRS相比,CCS可以更加高效地进行列操作,如列相加、列相减、列乘以常数等。

CCS常用于图论、网络分析等领域。

例如,在图论中,常常需要对邻接矩阵进行列操作,如计算图的邻接节点、计算图的度数等。

CCS 可以快速对非零元素所在的列进行操作,提高计算效率。

三、对角线压缩存储法(Diagonal Storage)对角线压缩存储法是一种适用于具有特殊结构的稀疏矩阵的压缩存储方法。

在对角线压缩存储法中,只存储矩阵的非零主对角线元素以及非零副对角线元素,其余元素均为0。

通过存储非零对角线元素及其位置,可以进一步减少存储空间。

对角线压缩存储法适用于具有对称或反对称性质的矩阵。

在数值计算、网络传输等领域,经常需要处理对称或反对称矩阵。

对角线压缩存储法可以有效存储这类特殊结构的矩阵,并提高运算效率。

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

稀疏矩阵的存储及运算存储什么是稀疏矩阵?人们无法给出确切的定义,它只是一个凭人们的直觉来了解的概念。

假若在m*n的矩阵中,非零元个数num<<m+n,我们可以称之为稀疏矩阵,并称t= num/(m*n) 为矩阵的稀疏因子。

通常认为t<<0.05时称为稀疏矩阵。

存储稀疏矩阵时,往往只存放其中的非零元。

稀疏矩阵的三元组表法是顺序存储方法的一种。

采用这种方法时,线性表中的每个结点对应稀疏矩阵的一个非零元素,其中包括3个字段,分别为该元素的行下标、列下标和值,结点间的次序按矩阵的行优先顺序排列。

另外,用第0行的三个元素分别存储矩阵的行数、列数和非零元数目。

例如,矩阵A:50 0 70 1 0 010 0 0 可以用三元组表示为: 3 4 41 1 51 4 72 2 13 1 1在具体编程过程中,往往可以用一个简单的n*3二数组来表示此三元组。

即稀疏矩阵A可以用数组a[5][3]={{3,4,4},{1,1,5},{1,4,7},{2,2,1},{3,1,1}} 来表示。

运算1)矩阵转置(带回溯)由于稀疏矩阵中的元素的存储是按行优先存储的,因此三元组中数据的行下标递增有序,行下标相同时列下标递增有序。

存储转置后的矩阵,只要将三元组a的第一行依次将a中的列值由小到大进行选择,将选中的三元组元素行列值互换后放入三元组b,直到三元组a中的元素全部放入b中为止。

2)不带回溯的转置不带回溯的转置要解决的关键问题是要预先确定好矩阵的每一列第一个非零元素在三元组b中应有的位置。

为了确定这些位置,转置前必须求得三元组a 中每一列非零元的个数,从而得到每列第一个元素在三元组b中(行)的位置。

用pot数组来记录。

pot[1]=1;pot[col]=pot[col-1]+第col-1列非零元的个数(pot[col])3)矩阵相加 C = A + B稀疏矩阵相加采用的算法思想是:依次扫描 A和B的行号和列号,如果A 的当前项的行号等于B的当前项的行号,则比较其列号,将较小的项存入C。

若列号也相等,则将对应的元素相加后存入C;若A的当前项的行号小于B的,则将A的项存入C,否则将B的项存入C。

[注]:if a[i][0]= = b[i][0]&& a[i][1]< b[i][1] 表明该位置上B矩阵为零而A矩阵的元素不为零,相加后的C矩阵的该位置元素应为A矩阵的该元素,故将较小者存入C。

4)矩阵相乘C = A * B矩阵的乘法涉及到两矩阵不同行,列之间的运算,情况相对复杂。

稀疏矩阵的乘法采用普通矩阵相乘的基本方法,关键是通过给顶的行号和列号找出原矩阵对应的元素值。

这里设计一个函数value,当在三元组表示中找到时返回其元素值,找不到时,说明该位置为0,因此返回0。

然后利用该函数计算出C的行号i和列号j 处的元素值,若该值不为0,则存入其三元组表示的矩阵,否则不存入。

完整的参考C程序如下:#include <stdio.h>#define max 20convert(int a[max][3],int a1[max][3]){int p,q,col;a1[0][0]=a[0][1];a1[0][1]=a[0][0];a1[0][2]=a[0][2];if(a1[0][2]!=0){q=1;for(col=1;col<=a[0][1];col++)for(p=1;p<=a[0][2];p++)if(a[p][1]==col){a1[q][1]=a[p][0];a1[q][0]=a[p][1];a1[q][2]=a[p][2];q++;}}}add(int a[max][3],int b[max][3],int c[max][3]) //error!!{int i=1,j=1,k=1;while(i<=a[0][2]&&j<=b[0][2]){if(a[i][0]==b[j][0]){if(a[i][1]<b[j][1]){c[k][0]=a[i][0];c[k][1]=a[i][1];c[k][2]=a[i][2];k++;i++;}else if(a[i][1]>b[j][1]) {c[k][0]=b[j][0];c[k][1]=b[j][1];c[k][2]=b[j][2];k++;j++;}else{c[k][0]=b[j][0];c[k][1]=b[j][1];c[k][2]=a[i][2]+b[j][2]; k++;i++;j++;}}else if(a[i][0]<b[j][0]) {c[k][0]=a[i][0];c[k][1]=a[i][1];c[k][2]=a[i][2];k++;i++;}else{c[k][0]=b[j][0];c[k][1]=b[j][1];c[k][2]=b[j][2];k++;j++;}c[0][0]=a[0][0];c[0][1]=a[0][1];c[0][2]=k-1;}}int value(int c[max][3],int i,int j){int k=1;while(k<=c[0][2]&&!(c[k][0]==i&&c[k][1]==j)) k++;if(c[k][0]==i&&c[k][1]==j)return(c[k][2]);else return(0);}multi(int a[max][3],int b[max][3],int c[max][3]) {int i,j,p,s,q;p=1;for(i=1;i<=a[0][0];i++)for(j=1;j<=b[0][1];j++){s=0;for(q=1;q<=a[0][1];q++)s=s+value(a,i,q)*value(b,q,j);if(s!=0){c[p][0]=i;c[p][1]=j;c[p][2]=s;p++;}}c[0][0]=a[0][0];c[0][1]=b[0][1];c[0][2]=p-1;}print(int a[max][3]){int i,j;for(i=0;i<=a[0][2];i++){for(j=0;j<=2;j++)printf(" %d",a[i][j]);printf("/n");}}main(){int a[max][3],b[max][3],a1[max][3],b1[max][3],c[max][3],d[max][3]; int i,y;printf("输入稀疏方阵A的行数,列数和非零元个数:");scanf("%d,%d,%d",&a[0][0],&a[0][1],&a[0][2]);for(i=1;i<=a[0][2];i++){printf("输入第%d个非0元素的行数,列数和值:",i);scanf("%d,%d,%d",&a[i][0],&a[i][1],&a[i][2]);}printf("输出A的三元组表示:/n");print(a);printf("/n输入稀疏方阵B的行数,列数和非零元个数:");scanf("%d,%d,%d",&b[0][0],&b[0][1],&b[0][2]);for(i=1;i<=b[0][2];i++){printf("输入第%d个非0元素的行数,列数和值:",i);scanf("%d,%d,%d",&b[i][0],&b[i][1],&b[i][2]);}printf("输出B的三元组表示:/n");print(b);printf("/n");printf("============= 菜单==============/n");printf(" 1 A矩阵转置/n");printf(" 2 B矩阵转置/n");printf(" 3 C = A + B/n");printf(" 4 D = A * B/n");printf("======================================/n/n");loop: printf("请选择相应操作的序号:");scanf("%d",&y);switch(y){case 1: convert(a,a1);printf("输出A转置的三元组表示:/n");print(a1);printf("/n");goto loop;case 2: convert(b,b1);printf("输出B转置的三元组表示:/n");print(b1);printf("/n");goto loop;case 3: add(a,b,c);printf("输出C=A+B的三元组表示:/n");print(c);printf("/n");goto loop;case 4: multi(a,b,d);printf("输出D=A*B的三元组表示:/n");print(d);printf("/n");goto loop;}}哪个提问。

记不住了。

补充:#include<iostream>using namespace std;class Matrix{private:int row,col;double **mx;public:Matrix(){}~Matrix();Matrix(Matrix &m);Matrix(int n,int m);friend Matrix operator*(Matrix &,Matrix &);friend istream & operator >>(istream &,Matrix &); friend ostream & operator <<(ostream &,Matrix &); friend Matrix operator+(Matrix &,Matrix &);friend Matrix operator-(Matrix &,Matrix &);friend Matrix operator!(Matrix &);};Matrix::Matrix(Matrix &m){int i,j;row=m.row;col=m.col;mx=new double *[row];for(i=0;i<row;i++)mx[i]=new double[col];for(i=0;i<m.row;i++)for(j=0;j<m.col;j++)mx[i][j]=m.mx[i][j];}Matrix::~Matrix(){int i;for(i=0;i<row;i++)delete [] mx[i];delete []mx;}Matrix::Matrix(int n,int m){int i,j;row=n;col=m;mx=new double *[row];for(i=0;i<row;i++)mx[i]=new double[col];for(i=0;i<row;i++)for(j=0;j<col;j++)mx[i][j]=0;}istream& operator>>(istream &input,Matrix &m) {int i,j;for(i=0;i<m.row;i++)for(j=0;j<m.col;j++)input>>m.mx[i][j];return input;}Matrix operator+(Matrix &m1,Matrix &m2){Matrix m(m1.row,m1.col);int i,j;for(i=0;i<m1.row;i++)for(j=0;j<m1.col;j++)m.mx[i][j]=m1.mx[i][j]+m2.mx[i][j];return m;}Matrix operator*(Matrix &m1,Matrix &m2){if(m1.col!=m2.row)throw 1;Matrix m(m1.row,m2.col);int i,j,t=0,s,l=0;for(i=0;i<m.col*m.row;i++){for(j=0,s=0;j<m2.row,s<m1.col;j++,s++) {m.mx[t][l]+=m1.mx[t][j]*m2.mx[s][l];}if((i+1)%m.col==0) {t++;l=0;}else l++;}return m;}ostream& operator<<(ostream &output,Matrix &m) {int i,j;for(i=0;i<m.row;i++)for(j=0;j<m.col;j++){output<<m.mx[i][j]<<"\t";if(j==m.col-1) cout<<endl;}return output;}Matrix operator-(Matrix &m1,Matrix &m2){Matrix m(m1.row,m1.col);int i,j;for(i=0;i<m1.row;i++)for(j=0;j<m1.col;j++)m.mx[i][j]=m1.mx[i][j]-m2.mx[i][j];return m;}Matrix operator!(Matrix &m1){int i,j;Matrix m(m1.col,m1.row);for(i=0;i<m1.row;i++)for(j=0;j<m1.col;j++)m.mx[j][i]=m1.mx[i][j];return m;}int main(){int n,m;int n1,n2;cout<<"**********加法与减法**********"<<endl; cout<<"请输入行数与列数:";cin>>n>>m;Matrix m1(n,m);cout<<"输入第一个矩阵:"<<endl;cin>>m1;Matrix m2(n,m);cout<<"输入第二个矩阵:"<<endl;cin>>m2;Matrix m3(m1+m2);cout<<"两矩阵相加后:"<<endl;cout<<m3<<endl;cout<<"两矩阵相减后:"<<endl;Matrix m31(m1-m2);cout<<m31<<endl;cout<<"**********乘法*********"<<endl;cout<<"请输入第一个矩阵的行与列:";cin>>n>>m;Matrix m4(n,m);cout<<"输入第一个矩阵:"<<endl;cin>>m4;cout<<"请输入第二个矩阵的行与列:";cin>>n1>>n2;Matrix m5(n1,n2);cout<<"输入第二个矩阵:"<<endl;cin>>m5;try{Matrix m6(m4*m5);cout<<"两矩阵相乘后:"<<endl;cout<<m6<<endl;}catch(int){cout<<"第一个矩阵的列数不等于第二个矩阵的行数,所以不能相乘!"<<endl;}cout<<"**********转置**********"<<endl;cout<<"请输入矩阵的行与列:";cin>>n>>m;Matrix m7(n,m);cout<<"输入一个矩阵:"<<endl;cin>>m7;Matrix m8(!m7);cout<<"转置后:"<<endl;cout<<m8;return 0;}-----------------------------------------------------------------------S P A R S K I T V E R S I O N 2.-----------------------------------------------------------------------Latest update : Tue Mar 8 11:01:12 CST 2005-----------------------------------------------------------------------Welcome to SPARSKIT VERSION 2. SPARSKIT is a package of FORTRAN subroutines for working with sparse matrices. It includes general sparse matrix manipulation routines as well as a fewiterativesolvers, see detailed description of contents below.Copyright (C) 2005, the Regents of the University of MinnesotaSPARSKIT is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation [version 2.1 of the License, or any later version.]A copy of the licencing agreement is attached in the file LGPL. For additional information contact the Free Software Foundation Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA or visit the web-site/copyleft/lesser.htmlDISCLAIMER----------SPARSKIT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warrantyofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.For more information contact saad@---------------------------------------------------S P A R S K I T VERSION 2---------------------------------------------------In this directory you will find all relevant subdirectories and the Unix makefile which will compile all the modules and make a unix library libskit.a. Please read the makefile. Making the library should be the first thing to do when starting to use the package. Some of the objects will be linked into a librarycalledlibskit.a. Others will not be linked but can be used by other makefiles for test problems provided in the subdirectories. You can then link to libskit.a by default instead of theindividualmodules. (Please report any compilation problems or (even minor) warnings immediatly to saad@). Once this is done, it is recommended to run the test problems provided. There are various test suites in each of the subdirectories and makefiles are available for each. See explanations in the README files in each individual subdirectory.You may also make and run the test programs using the dotests script provided in this directory. Output from this script may be redirected into a file and compared to the sample output files out.xxx. There is an additional script called sgrep which is useful for looking for tools in all the subdirectories. Read the sgrep fileforinstructions.-----------------------------------------------------------------------Here is some information on the SPARSKIT sub-directories.BLASSM : Basic linear algebra with sparse matrices.contains two modules: blassm.f and matvec.fDOC : contains the main documentation of the packageINFO : information routine (new one) . Info2 (spectralinformation) not available yet.FORMATS: Contains the Format Conversion routines informats.f and the manipulation routines inunary.fINOUT : input output routines. contains the module inout.fITSOL : contains the iterative solution package. Variousiterative solvers and preconditioners are provided.MATGEN : matrix generation routines.contains the module genmat.f and several subroutinescalled by it. Also contains zlatev.f (contributedby E. Rothman, from Cornell).ORDERINGS:still in the works. But contains a few coloring routinesand level-set related orderings -- (e.g., cuthill Mc Kee, etc.)UNSUPP : various `unsupported' routines and drivers.(misc. routines includind routines forplotting.. BLAS1 is also added for completeness)See the file "logfile" for a complete revision history.Report any problems, suggestions, etc.. toYousef Saad.saad at cs dot umn dot edu-----------------------------------------------------------------------稀疏矩阵运算器(纯C编写#include "string.h"#include "ctype.h"#include "malloc.h"#include "stdio.h"#include "stdlib.h"#include "conio.h"#include "mem.h"#include "alloc.h"#define OK 1#define ERROR 0#define MAXSIZE 100#define MAXRC 20typedef int Status;typedef int ElemType;typedef struct{int i,j;ElemType e;}Triple;typedef struct{Triple data[MAXSIZE+1]; /* 非零元三元组表,data[0]未用 */ int rpos[MAXRC+1]; /* 各行第一个非零元素的位置表*/int mu,nu,tu; /* 矩阵的行数、列数和非零元个数*/}RLSMatrix;typedef struct OLNode{int i,j;ElemType e;struct OLNode *right,*down;}OLNode,*OLink;typedef struct{OLink *rhead,*chead;int mu,nu,tu;}CrossList;Status CreateSMatrix(RLSMatrix *M);void DestroySMatrix(RLSMatrix *M);void PrintSMatrix(RLSMatrix M);Status ADD(RLSMatrix M,RLSMatrix N,RLSMatrix *Q);Status SubtS(RLSMatrix M,RLSMatrix N,RLSMatrix *Q);Status Mult(RLSMatrix M,RLSMatrix N,RLSMatrix *Q);Status FastTransposeSMatrix(RLSMatrix M,RLSMatrix *T);int menu_select();Status Operate(RLSMatrix A,RLSMatrix B,RLSMatrix *C);Status Exchange(RLSMatrix M,CrossList *N);Status Show(CrossList N);Status Change(RLSMatrix A,RLSMatrix B,RLSMatrix C,CrossList *M);Status DestoryCrossList(CrossList *M);void About();main(){RLSMatrix A,B,C;CrossList N;clrscr();About();for(;;){switch(menu_select()) /*调用主菜单函数,返回值做开关语句的条件*/{case 1:clrscr();printf("\n\n\n\t-------------Create Sparse Matrix A-----------------"); CreateSMatrix(&A); break;case 2:clrscr();printf("\n\n\n\t-------------Create Sparse Matrix B-----------------"); CreateSMatrix(&B); break;case 3:Operate(A,B,&C);break;case 4:Change(A,B,C,&N); break;case 5:About();break;case 6:DestroySMatrix(&A);DestroySMatrix(&B);DestroySMatrix(&C);DestoryCrossList(&N);exit(0);}}}int menu_select(){char *menu[]={"","",""," +--------------MENU--------------+", /*定义菜单字符串数组*/ " | |"," | 1.Create Sparse Matrix A |"," | 2.Create Sparse Matrix B |"," | 3.Operate |"," | 4.Change into CrossList |"," | 5.About... |"," | 6.Quit |"," | |"," | |"," +--------------------------------+"," By Zacard"," 06 07 10",};char s[3]; /*以字符形式保存选择号*/int c,i; /*定义整形变量*/gotoxy(1,25);printf("Any key to enter menu......\n");getch();clrscr();for(i=0;i<16;i++) /*输出主菜单数组*/{ gotoxy(10,i+1);cprintf("%s",menu[i]);}window(1,1,80,25); /*恢复原窗口大小*/gotoxy(10,21);do{printf("\n Enter your choice(1~6):");scanf("%s",s);c=atoi(s); /*将输入的字符串转化为整形数*/}while(c<1||c>6);return c; /*返回选择项,主程序根据该数调用相应的函数*/}Status CreateSMatrix(RLSMatrix *M) /* 创建稀疏矩阵M */{int i; /*用于暂存data域内容*/Triple T;int flag=0,mis; /*标志,输入正确为0*/printf("\nPlease input the row,col,and nonzero element number of the Sparse Matrix.");printf("\nForm:row num,col num,nonzero element num\n");scanf("%d,%d,%d",&(*M).mu,&(*M).nu,&(*M).tu);(*M).data[0].i=0; /* 为以下比较做准备 */for(i=1;i<=(*M).tu;i++){ mis=0;do{if(flag){printf("ERROR INPUT!\n");flag=0;mis++;}if(mis==3){printf("Fail Create !");return OK;}printf("Please input the row,col and value of the %dth nonzero element:",i);scanf("%d,%d,%d",&T.i,&T.j,&T.e);if(T.i<1||T.i>(*M).mu||T.j<1||T.j>(*M).nu) /* 行或列超出范围 */flag=1;if(T.i<(*M).data[i-1].i||T.i==(*M).data[i-1].i&&T.j<=(*M).data[i-1].j) /* 没有按顺序输入非零元素 */ flag=1;}while(flag); /* 当输入有误,重新输入 */(*M).data[i]=T;}for(i=1;i<=(*M).tu;i++) /* 计算rpos[] */for(T.i=0;T.i<(*M).data[i].i-(*M).data[i-1].i;T.i++) /* (*M).data[i]为第一个非0元素 */(*M).rpos[(*M).data[i].i-T.i]=i;for(i=(*M).data[(*M).tu].i+1;i<=(*M).mu;i++) /* 给最后没有非零元素的几行赋值 */(*M).rpos[i]=(*M).tu+1;PrintSMatrix(*M);return OK;}void PrintSMatrix(RLSMatrix M) /* 输出稀疏矩阵M */{int i,j,k;printf("\n ");for(i=1,k=1;i<=M.mu;i++){for(j=1;j<=M.nu;j++){if(M.data[k].i==i&&M.data[k].j==j){printf("%d\t",M.data[k].e); k++;}else printf("0\t");while(j==M.nu){printf("\n ");break;}}}}Status ADD(RLSMatrix M,RLSMatrix N,RLSMatrix *Q) /* 求稀疏矩阵的和Q=M+N */{int k,p,q;if(M.mu!=N.mu||M.nu!=N.nu) return ERROR;(*Q).mu=M.mu;(*Q).nu=M.nu;(*Q).tu=0;M.rpos[M.mu+1]=M.tu+1; /* 为方便后面的while循环临时设置 */N.rpos[N.mu+1]=N.tu+1;for(k=1;k<=M.mu;++k) /* 对于每一行,k指示行号 */{(*Q).rpos[k]=(*Q).tu+1;p=M.rpos[k]; /* p指示M矩阵第k行当前元素的序号 */q=N.rpos[k]; /* q指示N矩阵第k行当前元素的序号 *//* 当某一行不存在非零元素时,它对应的非零位置表的值为下一个非零元素的位置*/while(p<M.rpos[k+1]&&q<N.rpos[k+1]) /* 故当某行非零元位置等于下一行非零元位置时,它不存在非零元素*/ { /* M,N矩阵均有第k行元素未处理 */if(M.data[p].j==N.data[q].j) /* M矩阵当前元素和N矩阵当前元素的列相同 */{(*Q).data[(*Q).tu+1].e=M.data[p].e+N.data[q].e; /* 位置相同*/if((*Q).data[(*Q).tu+1].e!=0) /* 相加结果为0?*/{++(*Q).tu;(*Q).data[(*Q).tu].i=k;(*Q).data[(*Q).tu].j=M.data[p].j;}++p;++q;}else if(M.data[p].j<N.data[q].j){ /* M矩阵当前元素的列<N矩阵当前元素的列 */++(*Q).tu;(*Q).data[(*Q).tu].e=M.data[p].e;(*Q).data[(*Q).tu].i=k;(*Q).data[(*Q).tu].j=M.data[p].j;++p;}else /* M矩阵当前元素的列>N矩阵当前元素的列 */{++(*Q).tu;(*Q).data[(*Q).tu].e=N.data[q].e;(*Q).data[(*Q).tu].i=k;(*Q).data[(*Q).tu].j=N.data[q].j;++q;}}while(p<M.rpos[k+1]) /* M矩阵还有k行的元素未处理 */{++(*Q).tu;(*Q).data[(*Q).tu].e=M.data[p].e;(*Q).data[(*Q).tu].i=k;(*Q).data[(*Q).tu].j=M.data[p].j;++p;}while(q<N.rpos[k+1]) /* N矩阵还有k行的元素未处理 */{++(*Q).tu;(*Q).data[(*Q).tu].e=N.data[q].e;(*Q).data[(*Q).tu].i=k;(*Q).data[(*Q).tu].j=N.data[q].j;++q;}}return OK;}Status SubtS(RLSMatrix M,RLSMatrix N,RLSMatrix *Q) /* 求稀疏矩阵的差Q=M-N */ {int i;if(M.mu!=N.mu||M.nu!=N.nu) return ERROR;for(i=1;i<=N.tu;++i) /* 对于N的每一元素,其值乘以-1 */N.data[i].e*=-1;ADD(M,N,Q); /* Q=M+(-N) */return OK;}Status Mult(RLSMatrix M,RLSMatrix N,RLSMatrix *Q) /* 求稀疏矩阵乘积Q=M*N*/ {int arow,brow,p,q,ccol,ctemp[MAXRC+1]; /* ctemp[MAXRC+1]为列元素累加器*/if(M.nu!=N.mu) return ERROR; /* 矩阵M的列数应和矩阵N的行数相等 */(*Q).mu=M.mu; /* Q初始化 */(*Q).nu=N.nu;(*Q).tu=0;M.rpos[M.mu+1]=M.tu+1; /* 为方便后面的while循环临时设置 */N.rpos[N.mu+1]=N.tu+1;if(M.tu*N.tu!=0) /* M和N都是非零矩阵 */{for(arow=1;arow<=M.mu;++arow){ /* 从M的第一行开始,到最后一行,arow是M的当前行 */for(ccol=1;ccol<=(*Q).nu;++ccol)ctemp[ccol]=0; /* Q的当前行的各列元素累加器清零 */(*Q).rpos[arow]=(*Q).tu+1; /* Q当前行的第1个元素位于上1行最后1个元素之后 */ for(p=M.rpos[arow];p<M.rpos[arow+1];++p){ /* 对M当前行中每一个非零元 */brow=M.data[p].j; /* 找到对应元在N中的行号(M当前元的列号) */for(q=N.rpos[brow];q<N.rpos[brow+1];++q){ccol=N.data[q].j; /* 乘积元素在Q中列号 */ctemp[ccol]+=M.data[p].e*N.data[q].e;}} /* 求得Q中第arow行的非零元 */for(ccol=1;ccol<=(*Q).nu;++ccol) /* 压缩存储该行非零元 */if(ctemp[ccol]){if(++(*Q).tu>MAXSIZE) return ERROR;(*Q).data[(*Q).tu].i=arow;(*Q).data[(*Q).tu].j=ccol;(*Q).data[(*Q).tu].e=ctemp[ccol];}}}return OK;}Status FastTransposeSMatrix(RLSMatrix M,RLSMatrix *T){int col,p,q,t,num[MAXRC+1],cpot[MAXRC+1];(*T).mu=M.nu; /* num[]存M每列非0元个数 */(*T).nu=M.mu; /* cpot[]存每列第一个非0元序号 */(*T).tu=M.tu;if((*T).tu){for(col=1;col<=M.nu;++col) num[col]=0;for(t=1;t<=M.tu;++t) ++num[M.data[t].j];cpot[1]=1;for(col=2;col<=M.nu;++col) cpot[col]=cpot[col-1]+num[col-1];for(p=1;p<=M.tu;++p){col=M.data[p].j; q=cpot[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;++cpot[col];}}PrintSMatrix(M);printf("\nTranspose:\n");PrintSMatrix(*T);return OK;}Status Operate(RLSMatrix A,RLSMatrix B,RLSMatrix *C){int c;char t;do{clrscr();printf("\nInput your choice:\n(ADD--1,SUB--2,MUL--3,Transpose A--4,Transpose B--5,QUIT--any except 1~5)\n");scanf("%d",&c);switch(c){case 1:if(A.mu!=B.mu||A.nu!=B.nu){printf("Can't,condition misfit!\n");break;}ADD(A,B,C);PrintSMatrix(A);printf("\n\t(+)\n");PrintSMatrix(B);printf("\n\t(=)\n");PrintSMatrix(*C);break;case 2:if(A.mu!=B.mu||A.nu!=B.nu){printf("Can't,condition misfit!\n");break;}SubtS(A,B,C);PrintSMatrix(A);printf("\n\t(-)\n");PrintSMatrix(B);printf("\n\t(=)\n");PrintSMatrix(*C);break;case 3:if(A.nu!=B.mu){printf("Can't,condition misfit\n");break;}Mult(A,B,C);PrintSMatrix(A);printf("\n\t(*)\n");PrintSMatrix(B);printf("\n\t(=)\n");PrintSMatrix(*C);break;case 4:FastTransposeSMatrix(A,C);break;case 5:FastTransposeSMatrix(B,C);break;default: return OK;}/* switch */printf("Want to continue? (y/n)?");t=getch();}while(t=='y');return OK;}void DestroySMatrix(RLSMatrix *M) /* 销毁稀疏矩阵M(使M为0行0列0个非零元素的矩阵) */ {(*M).mu=0;(*M).nu=0;(*M).tu=0;}稀疏矩阵的加减法、乘法、求逆运算2010-11-16 21:27:07| 分类:数据结构与算法|举报|字号订阅#include <iostream>#include <iomanip>using namespace std;const int MAXSIZE = 100; //定义非零元素的最多个数const int MAXROW = 10; //定义数组行数的最大值const int SIZENUM = 10;typedef struct //定义三元组元素{int r, c; //矩阵的行号和列号int v; //矩阵元素值}Triple;typedef struct //定义普通三元组对象{Triple data[MAXSIZE+1];int rows, cols, nzeroNums; //行数、列数、非零元素个数}TSMatrix;typedef struct //定义行逻辑链接的顺序表{Triple data[MAXSIZE+2]; //非0元三元组表int rpos[MAXROW+1]; //各行第一个非零元素的位置表 int rows, cols, nzeroNums; //行数、列数、非零元素个数}RLSMatrix;//输入三元组矩阵template <class T>bool InputTSMatrix(T &M, int y){cout << "输入矩阵的行数、列数和非零元素个数: ";cin >> M.rows >> M.cols >> eroNums;cout << "请输入非零元素对应的行号、列号和相应的元素值: " << endl; for (int i = 1; i <= eroNums; i++){cin >> M.data[i].r >> M.data[i].c >> M.data[i].v;}return true;}//输出矩阵,按标准格式输出template <class T>bool OutputSMatrix(T M){int i, j, k = 1;for (i = 0; i < M.rows; i++){for (j = 0; j < M.cols; j++){if ((M.data[k].r-1) == i && (M.data[k].c-1) == j){cout << setw(4) << M.data[k].v;k++;}elsecout << setw(4) << "0";}//end_jcout << endl;}//end_ireturn true;}//求稀疏矩阵的转置int TranSMatrix(){TSMatrix M, T;InputTSMatrix(M, 0);int col, p, q = 1;T.rows = M.cols;T.cols = M.rows;eroNums = eroNums;if (eroNums){for (col = 1; col <= M.cols; col++){for (p = 1; p <= eroNums; p++){if (M.data[p].c == col){T.data[q].r = M.data[p].c;T.data[q].c = M.data[p].r;T.data[q].v = M.data[p].v;++q;}}//end_p}//end_col}//end_ifcout << "运用普通转置算法, 输入矩阵的转置矩阵为: " << endl;OutputSMatrix(T);return 1;}//稀疏矩阵的快速转置int FastTranMat(){TSMatrix M, T;int num[MAXROW+1]; //表示矩阵M中第col列非零元素的个数int cpot[MAXROW+1]; //表示矩阵M中第col列第一个非0元素在b.data中的位置int p, q, col, t;InputTSMatrix(M, 0); //输入稀疏矩阵T.rows = M.cols;T.cols = M.rows;eroNums = eroNums;if (eroNums){for (col = 1; col <= M.cols; col++)//M中各列元素初始化{num[col] = 0;}for (t = 1; t <= eroNums; t++){++num[M.data[t].c]; //求M中每一列非零元个数 }//求第col列第一个非零元在b.data中的序号cpot[1] = 1;for (col = 2; col <= M.cols; col++){cpot[col] = cpot[col-1] + num[col-1];}for (p = 1; p <= eroNums; p++){col = M.data[p].c; //稀疏矩阵M中每个元素对应的列号q = cpot[col]; //稀疏矩阵M中第一个非零元素位置T.data[q].r = M.data[p].c;T.data[q].c = M.data[p].r;T.data[q].v = M.data[p].v;++cpot[col];}//end_for}//end_ifcout << "运用快速算法,输入矩阵的转置为: " << endl;OutputSMatrix(T);return 1;}//求取稀疏矩阵每一行非零元个数bool Count(RLSMatrix &M){int row, p;int num[MAXROW+1];for (row = 1; row <= M.rows; row++){num[row] = 0; //清零}for (p = 1; p <= eroNums; p++){++num[M.data[p].r]; //统计M每一行非零元个数}M.rpos[1] = 1;//M中每一行非零元的起始位置for (row = 2; row <= M.rows; row++){M.rpos[row] = M.rpos[row-1] + num[row-1];}return true;}//两个稀疏矩阵的乘法bool MultSMatrix(){RLSMatrix M, N, Q; //构建三个带链接信息的三元组表示的数组 InputTSMatrix(M, 1); //用普通三元组形式输入数组InputTSMatrix(N, 1);Count(M);Count(N);if (M.cols != N.rows){cout << "Error!";return false;}//Q的初始化Q.rows = M.rows;Q.cols = N.cols;eroNums = 0;int mrow, nrow, p, q, t, tp, qcol;int ctemp[MAXROW+1]; //辅助数组//如果Q是非零矩阵if (eroNums * eroNums){for (mrow = 1; mrow <= M.rows; mrow++){//当前行各元素累加器清零for (int x = 1; x <= N.cols; x++){ctemp[x] = 0;}//end_x//当前行的首个非零元素在三元组中的位置为此行前所有非0元素加1Q.rpos[mrow] = eroNums + 1;if (mrow < M.rows){tp = M.rpos[mrow+1];}elsetp = eroNums + 1;for (p = M.rpos[mrow]; p < tp; p++) //对当前行的每个非零元素操作{nrow = M.data[p].c; //在N中找到与M操作元素的c值相等的行值rif (nrow < N.rows){t = N.rpos[nrow+1];}elset = eroNums + 1;//对找出的行的每个非零元素进行操作for (q = N.rpos[nrow]; q < t; q++){qcol = N.data[q].c;//将乘得到的对应值放在相应元素的累加器里面ctemp[qcol] += M.data[p].v * N.data[q].v;}}//p_end_for//对已经求出的累加器中的值压缩到Q中for (qcol = 1; qcol <= Q.cols; qcol++){if (ctemp[qcol]){if (++eroNums > MAXSIZE){cout << "Error!" << endl;return 0;}Q.data[eroNums].r = mrow;Q.data[eroNums].c = qcol;Q.data[eroNums].v = ctemp[qcol];}}//qcol_end_for}//arow_end_for}//end_ifcout << "两个稀疏矩阵相乘的结果为:\n";OutputSMatrix(Q);return 1;}//两个稀疏矩阵的加法int AddMatrix(){TSMatrix A, B, C;int i = 1, j = 1, k = 1; //i, j, k分别用以保存A、B、C非零元素个数 int value = 0;InputTSMatrix(A, 0);InputTSMatrix(B, 0);if (A.rows != B.rows || A.cols != B.cols){cout << "两个稀疏矩阵的大小不等,不能相加!" << endl;return 0;}if (A.rows == B.rows && A.cols == B.cols){while (i <= eroNums && j <= eroNums) {if (A.data[i].r == B.data[j].r){if (A.data[i].c < B.data[j].c){C.data[k].r = A.data[i].r;C.data[k].c = A.data[i].c;C.data[k].v = A.data[i].v;k++;i++;}else if (A.data[i].c > B.data[j].c){C.data[k].r = B.data[j].r;C.data[k].c = B.data[j].c;C.data[k].v = B.data[j].v;k++;j++;}else{value = A.data[i].v + B.data[j].v;if (value != 0){C.data[k].r = A.data[i].r;C.data[k].c = A.data[i].c;C.data[k].v = value;k++;}i++;j++;}}//end_ifelse if (A.data[i].r < B.data[j].r)。

相关文档
最新文档