1、数组的类型定义
数组是由类型相同的数据元素构成的有序集合,每个元素称为数组元素,每个元素受n(n>=1)个线性关系的约束,每个元素在n个线性关系中的序号i1,i2,···,in称为该元素的下标,可以通过下标访问该数据元素。因为数组中每个元素处于n(n>=1)个关系中,故称该数组为n维数组。数组可以看成线性表的推广,其特点是结果中的元素本身可以是具有某种结构的数据,但属于同i数据类型。
一维数组可以看成一个线性表,二维数组可以看成数据元素是线性表的线性表。
同理,一个n维数组类型可以定义为其数组元素为n-1维数组类型的一维数组类型。
数组一旦被定义,它的维数和维界就不再改变。因此,除了结构的初始化和销毁之外,数组只有存取元素和修改元素值的操作。
抽象数据类型数组可定义为:
ADT Arry{
数据对象:j(i)=0,···b(i)-1,i=1,2,···,n
D={a(j1j2···jn|n(>0)称为数组的维数,bi是数组第i维的长度,
ji是数组元素的第i维下标,aj1j2···jn属于ElemSet}
数据关系:R={R1,R2···,Rn}
Ri={<a(j1···j1···jn),a(j1···j1+1···jn)>|0<=jk<=bk-1,1<=k<=n 且k!=i,
0<=j(k)<=b(i-2) , a(ji···ji···jn),a(ji···ji+1···jn)属于D i=2 L n}
基本操作:
InitArry(&A,n,bound i,···,bound)
操作结果:若维数n和各维长度合法,则构造相应的数组A,并返回OK。
DestroyArray(&A)
操作结果:销毁数组A
Value(A,&e,indexl,···,indexn)
初始条件:A是n维数组,e为元素变量,随后是n个下标值
操作结果:若个下标不越界,则e赋值为所指定的A的元素值,并返回OK。
Assign(&A,e,indexl,···,indexn)
初始条件:A是n维数组,e为元素变量,随后是n个下标值。
操作结果:若下标不越界,则将e赋值为所指定的A的元素,并返回OK。
} ADT Array
2、数组的顺序储存
由于数组一般不进行插入或删除操作,一旦建立了数组则结构中的数据元素个数和元素之间的关系一般就不再发生变动,因此选择顺序结构来表示数组比较合适。
由于储存单元是一维的结构,而数组可能是多维的结构,则用一组连续储存单元存放数组的数据元素就有次序约定问题。对二维数组可以有两种储存方式:一种是以列序为主序的储存方式,另一种是以行序为主序的的储存方式。
对于数组,一旦规定了其维数和各维的长度,便可为这个数组分配储存空间。反之,只要给出了一组下标便可求得相应数组元素的储存位置。
以行序为主序:
假设每个数据元素占L个储存单元,则二维数组A[0···m-1,0···n-1](下标从0开始,共有m行n列)中任意元素a(ij)的储存位置可由下式确定:
LOC(i,j)=LOC(0,0)+(n*i+j)*L
以列序为主序:
二维数组A[0···m-1,0···n-1](下标从0开始,共有m行n列)中任意元素a(ij)的储存位置可由下式确定:
LOC(i,j)=LOC(0,0)+(n*i+j)*L
其中LOC(i,j)是a(ij)的储存位置;LOC(0,0)是a(00)的储存位置,即二维数组A的起始储存位置,也成为基地址或基址。
3、特殊矩阵的压缩储存
1.对称矩阵
若n阶矩阵A中的元满足 a(ij)=a(ji) 1<=i,j<=n ,则称为n阶对称矩阵。
对于对称矩阵,可以为每一对对称元分配一个储存空间,则可将n^2个元压缩储存到n(n+1)/2个元的空间中,不失一般性,可以行序为主序储存其下三角(包括对角线)中的元。
假设以一维数组sa[n(n+1)/2]作为n阶对称矩阵A的储存结构,则sa[k]和矩阵元a(ij)之间存在着一一对应关系:
k=i*(i-1)/2+j-1 (i>=j)
k=j*(j-1)/2+i-1 (i<j)
2.三角矩阵
以对角线划分,三角矩阵有上三角矩阵和下三角矩阵两种。上三角矩阵是指矩阵下三角中(不包括对角线)中的元均为常数c或0的n阶矩阵,下三角矩阵与之反之。对三角矩阵进行压缩除了核对成矩阵一样,只储存上(下)三角中的元素之外,再加一个储存常数c的储存空间即可。
1)上三角矩阵
sa[k]和矩阵元a(ij)之间的对应关系为:
k=(i-1)*(2n-i+2)/2+(i-j) i<=j
k=n*(n+1)/2 i>j
2)下三角矩阵
k=i*(i-1)/2+j-1 i>=j
k=n*(n+1)/2 i<j