稀疏矩阵的压缩存储

合集下载

矩阵的压缩存储

矩阵的压缩存储

二、稀疏矩阵的压缩存储
若矩阵中非零元素较少(非零元 素的个数栈元素总数的20%以 下),且分布没有明显的规律
1.三元组表示法 2.十字链表存储
1.三元组表示法
将其中的非零元素在一维数组空间中以行序为主序进行存储,在存储 非零元素的同时还要存储元素所在的行和列的位置 。
非零元素所在的行号、列号和元素值
4×4三角矩阵
存储结构
3.对角矩阵
若矩阵中所有的非零元素都集中在以对角线为中心的带状区域中,则 这类矩阵称为对角矩阵。
最常见的是三对角矩阵
存储 结构
存储方法:采用一维数组,对非零 元素按行顺序存储;n阶三对角矩 阵需要3n-2个元素的存储空间。
LOC(aij)=LOC(a11)+2(i-1)+j-1
int m, n, t;
//矩阵行数、列数和非零元素个数
}TSMatrix;
2.十字链表存储
当矩阵进行某些运算时,如加法、减法和乘法等,矩阵中非零元素的 个数和位置会发生很大的变化,适用链式存储结构——十字链表。 每个非零元素用一个结点表示,每个结点由5个域组成。
同一列中下一个非零元素的位置
同一行中下一个非零元素的位置
4×4对称矩阵
存储结构
用一维数组空间作为对n阶对称矩阵A的存储结构,则矩阵中任意元素 aij在一维数组中的位置为:
2.三角矩阵
若n阶矩阵A的上(或下)三角(不包括对角线)中的元素均为常数c或 零,则称矩阵A 为下(或上)三角矩阵。
三角矩阵存储方法: 用一个一维数组来存储其下(上)三角中的元素,除此之外,当上 (下)三角中的常数不为0时,还要增加一个常数c的存储空间。
存储结构
三元组表示法的类型定ห้องสมุดไป่ตู้:

河南师范大学稀疏矩阵的压缩存储

河南师范大学稀疏矩阵的压缩存储
for(int 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]++;
}
}
return 1;
设计程序如下:
#include<stdio.h>
#define MAXSIZE 12500
typedef struct{
int i,j;
int e;
}
Triple;
typedef struct{
Triple data[MAXSIZE+1];
int mu,nu,tu;
}TSMatrix;
int main(){
int FastTransposeSMatrix(TSMatrix M,TSMatrix &T);
TSMatrix M,T;char x;int i,j,p=1;
printf("请输入行:\n");
scanf("%d",&M.mu);
printf("请输入列:\n");
scanf("%d",&M.nu);
printf("请输入元素:\n");
while(1){
scanf("%d %d %d",&i,&j,&x);
if(x==-1)
break;
M.data[p].e=x;
M.data[p].i=i;

稀疏矩阵的压缩存储

稀疏矩阵的压缩存储

稀疏矩阵的压缩存储稀疏矩阵的压缩存储:实现稀疏矩阵压缩存储,并实现矩阵转置和求和。

输⼊矩阵时,⾸先需要输⼊⾮零元素的个数,然后分别输⼊矩阵的⾏号,列号和值。

输完2个矩阵后,⾃动进⾏计算第⼀个矩阵的转置以及两个矩阵的和。

例如:输⼊如下:100 90 5 //矩阵的⾏数为100,列数为90,共5个⾮零元素。

1 10 100 //a(1,10)=10050 60 200//a(50,60)=20050 80 100//a(50,80)=10060 60 200//a(60,60)=20099 89 10//a(99,89)=10100 90 2 //矩阵b的⾏数为100,列数为90,共2个⾮零元素。

1 1 10 //b(1,1)=1050 60 -200//b(50,60)=-200#include <iostream>using namespace std;struct Triple { //三元组int Row, Col; //⾮零元素⾏号/列号int value; //⾮零元素的值void operator = (Triple & R) //赋值{Row = R.Row; Col = R.Col; value = R.value;}};class SparseMatrix {private: //a = a*bint Rows, Cols, Terms; //⾏/列/⾮零元素数Triple *smArray; //三元组表public:SparseMatrix(int maxSize=100); //构造函数void Transpose(SparseMatrix& B); //转置SparseMatrix Add(SparseMatrix& b); //a = a+bfriend ostream& operator << (ostream& out, SparseMatrix &M);friend istream& operator >> (istream& in, SparseMatrix &M);};SparseMatrix::SparseMatrix(int maxSize){Terms = maxSize;smArray = new Triple[maxSize];Rows = Cols = 0;};void SparseMatrix::Transpose(SparseMatrix & B){int *rowSize = new int[Cols]; //列元素数数组int *rowStart = new int[Cols]; //转置位置数组B.Rows = Cols; B.Cols = Rows;B.Terms = Terms;if (Terms > 0) {int i, j;for (i = 0; i < Cols; i++) rowSize[i] = 0;for (i = 0; i < Terms; i++)rowSize[smArray[i].Col]++;rowStart[0] = 0;for (i = 1; i < Cols; i++)rowStart[i] = rowStart[i - 1] + rowSize[i - 1];for (i = 0; i < Terms; i++) {j = rowStart[smArray[i].Col];B.smArray[j].Row = smArray[i].Col;B.smArray[j].Col = smArray[i].Row;B.smArray[j].value = smArray[i].value;rowStart[smArray[i].Col]++;}}delete[] rowSize; delete[] rowStart;}SparseMatrix SparseMatrix::Add(SparseMatrix & b){SparseMatrix res;int i = 0, j = 0, index_a, index_b;res.Terms = 0;while (i < Terms&&j < b.Terms) {index_a = Cols * smArray[i].Row + smArray[i].Col;index_b = Cols * b.smArray[j].Row + b.smArray[j].Col;if (index_a < index_b) {res.smArray[res.Terms] = smArray[i];i++;}else if (index_a > index_b) {res.smArray[res.Terms] = b.smArray[j];j++;}else{int vv= smArray[i].value + b.smArray[j].value;if (vv != 0) {res.smArray[res.Terms] = smArray[i];res.smArray[res.Terms].value = vv;}if (vv == 0) {res.Terms--;}i++; j++;}res.Terms++;}for (; i < Terms; i++) {res.smArray[res.Terms] = smArray[i];res.Terms++;}for (; j < b.Terms; j++) {res.smArray[res.Terms] = b.smArray[j];res.Terms++;}return res;}ostream & operator<<(ostream & out, SparseMatrix & M){for (int i = 0; i < M.Terms; i++) {out << M.smArray[i].Row << " " << M.smArray[i].Col << " " << M.smArray[i].value << endl; }return out;// TODO: 在此处插⼊ return 语句}istream & operator>>(istream & in, SparseMatrix & M){in >> M.Rows >> M.Cols >> M.Terms;for (int i = 0; i < M.Terms; i++) {in >> M.smArray[i].Row >> M.smArray[i].Col >> M.smArray[i].value;}return in;// TODO: 在此处插⼊ return 语句}int main(){SparseMatrix s,s2,s3,s4;cin >> s;cin >> s3;s.Transpose(s2);cout << "The transformed matrix is:" << endl;cout << s2;s4=s.Add(s3);cout << "The added matrix is:" << endl;cout << s4;return 0;}。

稀疏矩阵压缩的存储方法

稀疏矩阵压缩的存储方法

稀疏矩阵压缩的存储方法
稀疏矩阵压缩存储方法是一种针对只有少量非零元素的矩阵进行存储的方法,以减少存储空间。

常见的稀疏矩阵压缩存储方法有三种:
1. COO(Coordinate Representation)坐标表示法:
将非零元素的行、列以及值分别存储起来。

可以用一个三元组的列表来表示,每个三元组包含非零元素的行、列和值。

这种方法的优点是简单直观,适用于非常稀疏的矩阵。

缺点是存储空间相对较大,查找和计算比较复杂。

2. CSR(Compressed Sparse Row)压缩行表示法:
将矩阵的行指针、列索引和非零元素的值分别存储起来。

行指针数组存储每一行的第一个非零元素在值数组中的索引位置,列索引和值数组分别存储每一个非零元素的列索引和值。

这种方法的优点是存储空间较小,查找和计算比较高效。

缺点是构造过程相对复杂,删除或插入元素可能导致数组的重新分配。

3. CSC(Compressed Sparse Column)压缩列表示法:
类似于CSR,只是做了行和列的交换。

列指针数组存储每一列的第一个非零元素在值数组中的索引位置,行索引和值数组分别存储每一个非零元素的行索引和值。

这种方法适用于以列为主要操作的稀疏矩阵运算。

注:以上方法仅是三种常见的压缩存储方法,实际上还有其他一些方法,如DIA (Diagonal)对角线表示法、ELL(Ellpack-Itpack)等,不同的方法适用于不同情况下的稀疏矩阵存储。

数据结构-稀疏矩阵的三元组表存储方法

数据结构-稀疏矩阵的三元组表存储方法

4 3 24 5 2 18
注意:
data 7 data 8
6 1 15 6 4 -7
mu=6 nu=7 tu=8
为了保存矩阵的行数、列 数和非零元素个数,还需 增设三个量:mu nu tu
3.三元组线性表的数据类型描述
#define MAXSIZE 12500 //非零元素个数的最大值
typedef struct{
用变量 a 存放矩阵 M 的形式如下:
a . data p i j e a .data 1 1 2 12 a .data 2 1 3 9 a .data 3 3 1 -3 a .data 4 3 6 14 a .data 5 4 3 24 a .data 6 5 2 18 a .data 7 6 1 15 a .data 8 6 4 -7 a. mu=6 a. nu=7 a. tu=8
用一个三元组(tupel3)存放矩阵中的 一个非零元素的行号、列号及该非零元素 的值。 一个三元组的形式为:(i , j, e)
一般情况下,一个稀疏矩阵中有若干个 非零元素,所以要用一个“三元组线性表” 来存放一个稀疏矩阵。
2.用顺序存储结构存放三元组线性表
存放形式: (按行顺序存放) data p i j e
a .data 5 4 3 24
b .data 5
a .data 6 5 2 18
b .data 6
a .data 7 6 1 15
b .data 7
a .data 8 6 4 -7
b .data 8
a. mu=6 a. nu=7 a. tu=8 注:p=1:8,寻找 j=col 的a.data[ p]
a. mu=6 a. nu=7 a. tu=8 求得

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

稀疏矩阵 存储方法

稀疏矩阵 存储方法

稀疏矩阵存储方法稀疏矩阵是指矩阵中绝大部分元素为0的矩阵。

在实际问题中,往往会遇到大规模的稀疏矩阵,对于这种矩阵的存储需要考虑如何高效地使用内存空间。

下面将介绍几种常见的稀疏矩阵存储方法。

1. 链接存储法:在这种方法中,我们可以使用一个链表来存储非零元素的位置和值。

具体做法是每个非零元素都使用一个结点来表示,结点中包括行、列和对应的元素值。

这样,对于每个非零元素,我们只需要包含它的位置信息和值即可,并且可以通过遍历链表来获取所有的非零元素。

2. 顺序表存储法:在顺序表存储法中,我们使用两个数组来保存非零元素的位置和值。

一个一维数组存储所有非零元素的位置,另一个一维数组存储对应的值。

在这种方法中,我们需要额外的辅助空间来保存非零元素的位置信息,但是对于获取元素值的操作会更加高效,因为我们可以直接通过索引来访问元素。

3. 排序顺序表存储法:与顺序表存储法类似,不同之处在于我们需要对非零元素的位置进行排序。

一种常见的排序方法是按照行优先顺序进行排序。

这样做的好处是在矩阵乘法运算等操作中,我们可以利用行优先的顺序,减少对非零元素的访问次数,从而提高运算效率。

4. 压缩存储法:在压缩存储法中,我们通过记录每行非零元素的数量以及每个非零元素的位置和值来表示稀疏矩阵。

具体做法是使用三个一维数组分别存储每行非零元素的数量、非零元素的列索引和对应的值。

这种方法可以极大地节省存储空间,并且对于访问非零元素的操作也很高效。

以上介绍的是几种常见的稀疏矩阵存储方法,它们各自的特点和适用场景也不同。

选择何种存储方法应该根据具体应用的需求来确定。

例如,在求解线性方程组或稀疏矩阵乘法运算时,可以选择压缩存储法;而在矩阵的插入、删除操作较为频繁时,可以考虑使用链表存储法。

总之,在实际应用中,我们需要根据问题的特点和存储空间的要求,综合考虑各种因素来选择最合适的存储方法。

第4讲稀疏矩阵压缩存储下——教学讲义

第4讲稀疏矩阵压缩存储下——教学讲义

第4讲稀疏矩阵压缩存储下——教学讲义“列序”递增转置法的思考:采用稀疏矩阵存储方法,可否降低时间复杂度?(提示:通过降低对稀疏矩阵三元组的扫描次数实现)方法二:“一次定位快速转置”法【算法思想】在方法一中,为了使转置后矩阵的三元组表B仍按“行序递增”存放,必须多次扫描被转置矩阵的三元组表A,以保证按被转置矩阵列序递增进行转置。

因此要通过双重循环来完成。

改善算法的时间性能,必须去掉双重循环,使整个转置过程通过一重循环来完成,即只对被转置矩阵的三元组表A扫描一次,就使A中所有非零元的三元组“一次定位”直接放到三元组表B的正确位置上。

为了能将被转置三元组表A中的元素一次定位到三元组表B的正确位置上,需要预先计算以下数据:( 1 )待转置矩阵三元组表A每一列中非零元素的总个数(即转置后矩阵三元组表B的每一行中非零元素的总个数)。

( 2 )待转置矩阵每一列中第一个非零元素在三元组表B中的正确位置(即转置后矩阵每一行中第一个非零元素在三元组表B中的正确位置)。

为此,需要设两个数组分别为num[]和position[]。

其中num[ col]用来存放三元组表A第col列中非零元素总个数(三元组表B第col行中非零元素的总个数)。

position[ col]用来存放转置前三元组表A中第col列(转置后三元组表B中第col行)中第一个非零元素在三元组表B中的存储位置(下标值)。

num[ col]的计算方法:将三元组表A扫描一遍,对于其中列号为col的元素,给相应的num 数组中下标为col的元素加1 。

说明:在num[ col]的计算中,采用了“数组下标计数法”。

position[ col]的计算方法:①position[ 1 ]=1 ,表示三元组表A中,列值为1的第一个非零元素在三元组表B中的下标值;②position[ col]=position[ col-1 ]+num[ col-1 ]。

其中2 ≤col≤A.n。

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

普通高等教育“十一五”国家级规划教材
• /*初始化数组A*/
1. Status InitialArray(Array &A, int Adim) 2. /*如果维数Adim和数组各维的长度bounds合法,构造相应的数组A, 并返回OK值*/ 3. { /*如果维数Adim不合法,返回值为error */ 4. if (Adim<1||Adim> MAXDIM) 5. return error ; 6. A.dim=Adim; 7. A.bounds=(int* )malloc(Adim*sizeof(int)); 8. if (!A.bounds) 9. exit (overflow); 10. /*如果各维长度合法,则存入A.bounds,并求出A的元素总数 totalnum*/ 11. totalnum=1; 12. va_start(ap, Adim); /*ap为存放变长参数表信息的数组,其类 型为va_list*/
• 推广到n维数组:
普通高等教育“十一五”国家级规划教材
A0 (1)
A1(1)
An-1 (1)
以列序为主序
以行序为主序
普通高等教育“十一五”国家级规划教材

1. 2. 3. 4. 5. 6. 7.
/*数组的顺序存储表示*/
typedef struct { ElemType *base; /*数组元素初始地址,由初始化操作实 现*/ int dim; /*数组的维数*/ int *bounds; /*数组各维的长度,也由初始化操作实现*/ int *const ; /*数组的映象函数常量的初始地址,由初始化操 作实现*/ } Array;
片连续的存储单元中
• 二维数组有两种存储方式:以列序为主序(column
major order)的存储方式,如图6-2(a)所示和以行序为 主序(row major order)的存储方式,如图6-2(b)所示
• 地址计算:以行序为主序的存储方式为例
LOC[i,j]=LOC[0,0]+(b2i+j) L
解答:
• (1) 由于C语言数组的行、列下界均为0,该数组行上 界为5-1=4,列上界为4-1=3,所以该数组的元素 共有5×4=20个 • (2)由于C语言采用行序为主的存储方式,根据式子6-1 : ,LOC[3,2]=LOC[0,0]+(b2i+j)L=2400+(4×3+2) ×4=2456
13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. }
for(i=0;i<Adim;++i) { A.bounds[i]=va_arg(ap,int); if(A.bounds[i]<0) return (underflow); totalnum* = A.bounds[i]; } va_end(ap); A.base=(ElemType*)malloc(dim*sizeof(ElemType)); if(!A.base) exit(overflow); /*求映象函数的常,把结果存入A.const [i-1],i=1,…,Adim*/ A.const=(int*)malloc(dim*sizeof(int)); if(!A.const) exit(overflow); A.const [Adim-1]=1; /*指针的增减以元素的大小为单位*/ for(i=Adim-2;i>=0,i--) A.const [i]=A.bounds[i+1]*A.const [i+1]; return OK;
• 数组(Array):由一组类型相同的数据元素构成的
有限序列,且该有限序列存储在一块地址连续的内存单 元中
• 一维数组 :数组只有一个下标 • 二维数组 :数组元素都含有两个下标 ,形如:
普通高等教育“十一五”国家级规划教材
• 二维数组与一维数组的关系:
一个二维数组看成是每个数据元素都是相同类型的 一维数组的一维数组
普通高等教育“十一五”国家级规划教材
• 例6-2: 现有m名考生,每人参加n门课程考试,试写出
任一考生的总分数和任一门课程总分数的算法
• 解答:
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. # define M 200 /*考生的人数*/ # define N 5 /*每个考生参加考试的课程门数*/ int Ascore[M][N] ; /*存放考生成绩的二维数组*/ /*求第i名考生的总分数*/ int StuScore ( int Ascore [ ][N] , int i) { int j , StuSum; StuSum = 0; /*赋初值*/ for ( j = 0 ; j < N ; j++ ) StuSum = StuSum +Ascore [ i-1][j]; /*求第i名考生的总分*/ return ( StuSum); }
普通高等教育“十一五”国家级规划教材
第6章 数组与广义表
• • • • • • 6.1 数组的定义及其基本操作 6.2 数组的顺序存储结构 6.3 矩阵的压缩存储 6.4 广义表的概念 6.5 广义表的存储结构表示 6.6 广义表的运算
Hale Waihona Puke 6.1 数组的定义及其基本操作 6.1.1 数组的定义
普通高等教育“十一五”国家级规划教材
普通高等教育“十一五”国家级规划教材
普通高等教育“十一五”国家级规划教材
例题6-1
对二维数组float array[5][4],计算: (1) 数组array中的数组元素数目 (2) 若数组array的起始地址为2400,且每个数组元素长 度为32位(即四个字节),数组元素array [3][2]的内 存地址
普通高等教育“十一五”国家级规划教材
6.1.2 数组的基本操作
• 随机存:给定一组下标,存一个数据元素到该组下标
对应的内存单元中
• 随机取:从给定的一组下标所对应的内存单元中取出
一个数据元素
普通高等教育“十一五”国家级规划教材
6.2 数组的顺序存储结构
• 数组的顺序存储结构:将数组元素顺序地存放在一
• 事例:m行n列的二维数组,可以看成是一个线形表
A=(a1,a2,…,ap) (p=m 或 n) 即:
普通高等教育“十一五”国家级规划教材

1. 2. 3. 4.
数组的性质:
数组中的数据元素数目固定 数组中的数据元素具有相同的数据类型。 数组中的每个数据元素都和一组唯一的下标值对应。 数组是一种随机存储结构,可随机存取数组中的任意 数据元素
相关文档
最新文档