1.矩阵的压缩存储
对于一些阶树很高的矩阵,如果有许多值相同的元素或者是零元素,可以对其进行压缩以节省存储空间。可以为多个值相同的元只分配一个存储空间;对零元不分配空间。
2.稀疏矩阵
什么是稀疏矩阵?
在一个m*n的矩阵中,有t个元素不为0,t/(m*n)称为稀疏因子,通常认为稀疏因子小于0.05时称为稀疏矩阵。
3.稀疏矩阵的压缩存储
1)三元组顺序表
#define MAXSIZE 12500 //非零元个数的最大值
typedef struct{
int i,j; //非零元的行下标和列下标
ElemType e;
}Triple;
typedef struct{
Triple data[MAXSIZE+1]; //非零元三元数组表,data[0]未用
int mu,nu,tu; //矩阵的行数、列数和非零元个数
}TSMatrix;
2)三元组顺序表存储稀疏矩阵的转置
算法1:
Status TransposeSMatrix(TSMatrix M, TSMatrix &T){
T.mu=M.mu; T.nu=M.nu; T.tu=M.tu;
if(T.tu){
q=1;
for(col=1;col<=M.nu;++col)//依次遍历原先矩阵M的每一列的非零元
for(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;}
}
return OK;
}
可以看出其时间复杂度为O(nu*tu),而一般转置的时间复杂度为O(mu*nu),可以看出仅仅适合tu《mu*nu时。
如果可以预先确定矩阵M中每一列(即T的每一行)的第一个非零元在其三元数组中的位置,那么对其转置时便可直接放到相应的三元数组的恰当位置上。这样就不用遍历M的每一列了。
因此需要引入两个辅助向量; num[col] M中第col列中非零元的个数
copt[col] M中第col列中第一个非零元的位置
显然
copt[1]=1;
copt[col]=copt[col-1]+num[col-1] 2 ≤col≤M.nu
算法2:快速转置
Status FastTransposeSMatrix(TSMatrix M, TSMatrix &T){
T.mu=M.mu; T.nu=M.nu; T.tu=M.tu;
if(T.tu){
for(col=1;col<=M.nu;++col) num[col]=0;
for(t=1;col<=M.tu;++t) ++num[M.data[t].j;
copt[1]=1;
for(col=2;col<=M.nu;++col) copt[col]=copt[col-1]+num[col-1];
for(p=1;p<=M.tu;++p){
col=M.data[p].j; q=copt[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;}
}
return OK;
}
其时间复杂度为O(nu+tu),当tu和mu*nu等数量级时,其时间复杂度和经典算法的时间复杂度相同。
3)行逻辑链接的顺序表
三元组顺序表的特点是在表中按行序有序的存储,若需按行号存取某一行的非零元,则需要从头开始找。为了便于随即存取任意一行的非零元,则需知道每一行的第一个非零元在三元组的位置。为次可讲上述中指示行信息的辅助数组copt固定在稀疏矩阵的存储结构中。这种带有行连接信息的三元组表称为行逻辑链接的顺序表。
typedef struct{
Triple data[MAXSIZE+1]; //非零元三元数组表
int rpos[MAXRC+1]; //各行第一个非零元的位置表
int mu,nu,tu; //矩阵的行数、列数和非零元个数
}RLSMatrix;
4)矩阵相乘
5)十字链表