数据结构中的线性结构包括线性表,栈,队列还有串,这些结构的数据元素都是不再分解的原子类型。数组和广义表可以看成是线性表在下述含义以上的扩展:表中的数据元素本身也是一个数据结构。
一、数组
1、和线性表一样,数组中所有的数据元素都必须属于统一数据类型。数组中的每个数据元素都对应于一组下标(j1,j2,...,jn),每个下标有各自的取值范围,0≤ji≤bi-1,bi称为第i维的长度(i=1,2,3,...,n)。当n=1时,n维数组就退化为定长的线性表。
n维数组也可以看成是线性表的推广。一个n维数组类型可以定义为起数据元素为n-1维数组类型的一维数组类型。除了初始化和销毁才做之外,数组只有存取元素和修改元素值的操作。
2、一般采用顺序存储结构表示数组。由于数组是多维的,则用一组连续存储单元存储数组的数据元素就得约定存储次序。对二维数组可有两种存储方式,即以列序为主序(高下标即最里层下标优先)和以行序为主序(低下标即最外层下标优先)的存储方式。
假设每个数据元素占L个存储单元,则二维数组A中任一元素的存储位置可由公式算出:LOC(i,j)=LOC(0,0)+(b2×i+j)L,LOC(0,0)是第一个元素a00的存储位置。
二、矩阵的压缩存储
有效存储矩阵的元,可使矩阵的各种运算能有效地进行。
所谓压缩存储:为多个值相同的元只分配一个存储空间;对零元不分配空间。
稀疏矩阵的压缩存储:
这类矩阵,其非零元较零元少,且分布没有一定规律。假设在m*n的矩阵中,有t个元素不为零。令=t/(m*n),称 为矩阵的稀疏因子。 《=0.05时称为稀疏矩阵。
存储局正式,除了存储非零元的值以外,还必须记下他所在的行和列的位置(i,j),一个三元组(i,j,aij)唯一确定了矩阵A的一个非零元。
基于三元组表不同的表示方法可以引出稀疏矩阵不同的压缩存储方法。
1、三元组顺序表
#define MAXSIZE 500
typedef struct{
int i,j; //该非零元的行下标和列下标
ElemType e;}Triple;
typedef struct{
Triple data[MAXSIZE+1]; //非零元三元组表,data[0]未用
int mu,nu,tu; //矩阵的行数,列数和非零元个数
}TSMatrix;
data域中表示非零元的三元组是以行序为主序顺序排列的。
快速转置算法:a.data和b.data表分别是稀疏矩阵M,T的非零元三元组表,T是M的转置矩阵。如果预先确定矩阵M中每一列即T中每一行的地一个非零元在b.data中应有的位置,那么在对a.data中的三元组依次作转置时,就可直接放到b,data中恰当的位置上去,从而实现转置时时间复杂度是线性的。
在转置前,应先求得原矩阵M中每一列非零元的个数,进而求得每一列的第一个非零元在b.data中应有的位置。
Status FastTransposeSMatrix(TSMatrix M,TSMatrix *T)
{ //快速求稀疏矩阵M的转置矩阵T
T.mu=M.nu;
T.nu=M.mu;
T.tu=M.tu;
if(T.tu)
{
for(col=1;col<=M.nu;++col)
num[col]=0; //设初值
for(t=1;t<=M.tu;++t) //求M中每一列含非零元素个数
++num[M.data[t].j];
cpot[1]=1;
for(col=2;col<=M.nu;++col) //求第col列中第一个非零元在b.data中的序号
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]; //下一次已+1
}
}
return OK;
}
2、行逻辑链接的顺序表
此存储结构可随机存取任意一行的非零元。将快速转置矩阵算法中指示“行”信息的辅助数组cpot固定在稀疏矩阵的存储结构中。
Typedef struct{
Triple data[MAXSIZE++1];
Int rpos[MAXRC+1];
Int mu,nu,tu;
}RLSMatrix;
算法描述:
Q初始化;
If(Q是非零矩阵){//逐行求积
For(arrow=1;arrow<=M.mu;++arow)
{//处理M中每一行
ctemp[]=0;//累加器清零
计算Q中第arow行的积并存入ctemp[]中
将ctemp[]中非零元压缩存储到Q.data中
}
}