将表示稀疏矩阵的非零元素的三元组按行优先(或列优先)的顺序排列(跳过零元素),并依次存放在向量中,这种稀疏矩阵的顺序存储结构称为三元组表。
(1)三元组表的类型说明
为了运算方便,将矩阵的总行数、总列数及非零元素的总数均作为三元组表的属性进行描述。其类型描述为:
#define MaxSize 10000 //由用户定义 typedef int DataType; //由用户定义 typedef struct { //三元组 int i,j;//非零元的行、列号 DataType v; //非零元的值 }TriTupleNode; typedef struct{ //三元组表 TriTupleNode data[MaxSize]; //三元组表空间 int m,n,t; //矩阵的行数、列数及非零元个数 }TriTupleTable;
(2) 压缩存储结构上矩阵的转置运算
一个m×n的矩阵A,它的转置矩阵B是一个n×m的矩阵,且:
A[i][j]=B[j][i],0≤i<m,0≤j<n,
即A的行是B的列,A的列是B的行。
①三元组表表示的矩阵转置的思想方法
第一步:根据A矩阵的行数、列数和非零元总数确定B矩阵的列数、行数和非零元总数。
第二步:当三元组表非空(A矩阵的非零元不为0)时,根据A矩阵三元组表的结点空间data(以下简称为三元组表),将A的三元组表a->data置换为B的三元组表b->data。
②三元组表的转置
方法一:简单地交换a->data中i和j中的内容,得到按列优先顺序存储倒b->data;再将b->data重排成按行优先顺序的三元组表。
方法二:由于A的列是B的行,因此,按a->data的列序转置,所得到的转置矩阵B的三元组表b->data必定是按行优先存放的。
按这种方法设计的算法,其基本思想是:对A中的每一列col(0≤col≤a->n-1),通过从头至尾扫描三元组表a->data,找出所有列号等于col的那些三元组,将它们的行号和列号互换后依次放人b->data中,即可得到B的按行优先的压缩存贮表示。具体实现参见【动画演示】
③具体算法:
void TransMatrix(TriTupleTable *b,TriTupleTable *a) {//*a,*b是矩阵A、B的三元组表表示,求A转置为B int p,q,col; b->m=a->n; b->n=a->m; //A和B的行列总数互换 b->t=a->t; //非零元总数 if(b->t<=0) Error("A=0"); //A中无非零元,退出 q=0; for(col=0;col<a->n;col++) //对A的每一列 for(p=0;p<a->t;p++) //扫描A的三元组表 if(a->data[p].j==col){ //找列号为col的三元组 b->data[q).i=a->data[p].j; b->data[q].j=a->data[p].i; b->data[q].v=a->data[p].v; q++; } } //TransMatrix
3、带行表的三元组表
为了方便某些矩阵运算,在按行优先存储的三元组表中,加入一个行表来记录稀疏矩阵中每行的非零元素在三元组表中的起始位置。这就是带行表的三元组表。
(1)类型描述
#define MaxRow l00 //在三元组表定义前加入此最大行定义 typedef struct { TriTupleNode data[MaxSize]; int RowTab[MaxRow];//行表,应保证m≤MaxRow int m,n,t; }RTriTup
leTable;
(2)带行表的三元组表的操作
①
对于任给行号i(0≤i≤m-1),能迅速地确定该行的第一个非零元在三元组表中的存储位置为RowTab[i]
②
RowTab[i](0≤i≤m-1)表示第i行之前的所有行的非零元数。
③
第i行上的非零元数目为RowTab[i+1]-RowTab[i](0≤i≤m-2)
④
最后一行(即第m-l行)的非零元数目为t-RowTab[m-1](t为矩阵的非零元总数)
注意:
若在行表中令RowTab[m]=t(要求MaxRow>m)会更方便 些,且t可省略。