1数组的定义—基于线性结构·
数组可看作普通线性表的推广的广义表
普通数组的各项操作都不会引起元素的插入或删除,故数组常采用顺序存储结构
ADT Array {
数据对象:D={aj1,j2,...jn|n为维数,设第i维长度为bi,则ji =0..bi-1}
数据关系:R={R1, R2, ..., Rn} //Ri代表第i维上的相邻关系
Ri={<aj1,.(ji),.jn , aj1..(ji+1)..jn > | 0≤jk≤ bk-1, 0≤ji≤bi-2…}
基本操作:
InitArray(&A,n,bound1,...,boundn)
//n为维数,boundi为第i维长度
DestroyArray(&A)
AssignValue(A, e, index1, ..., indexn)
//将指定下标的元素赋值为e
GetValue(A, &e, index1, ..., indexn)
//用e返回指定下标的元素的值
}//ADT Array
2数组的顺序表示和实现—计算元素存储位置
3 特殊矩阵的压缩存储
对称矩阵
稀疏矩阵
静态分配的三元组顺序表存储结构
#define MAXSIZE 12500
typedef struct {
int i, j; //非零元的下标
ElemType e; //非零元的值
} Triple; // 三元组类型
typedef struct{
Triple data[MAXSIZE + 1];//0不用,从1始
unsigned int mu,nu,tu;//行列阶数与非零元个数
} TSMatrix; // 三元组顺序表类型
矩阵转置(三元组顺序表实现)B=AT
关键原因在于要重复遍历多次顺序表,能否先遍历一次求出A中的元素在B中”应有”的位置,之后直接放入呢?
T.mu=S.nu; T.nu=S.mu; T.tu=S.tu;
if(T.tu){
loc=1; //目标三元素顺序表中当前的存储位置
for(col=1;col<=M.nu;++col) //原A中列号由小变大
for(k=1;k<=M.tu;++k) //遍历A中所有非零元素
if( M.data[k].j==col ) { //找列标等于col元素修改后入B
T.data[loc].e=M.data[k].e;
T.data[loc].i=M.data[k].j;
T.data[loc].j=M.data[k].i;
++index;
}
return OK;
}//复杂度O(M.nu*M.tu).二维数组转置O(M.nu*M.mu).当足够稀疏以致M.tu<M.mu时当前算法更有效,否则不然,最坏O(M.mu*M.nu2)
4 广义表的定义/存储与表示
经典例子
矩阵乘法经典算法Q=MN
for (i=1; i<=m1; ++i)
for (j=1; j<=n2; ++j) {
Q[i][j] = 0;
for (k=1; k<=n1; ++k)
Q[i][j] += M[i][k] * N[k][j];
}
其时间复杂度为: O(m1×n2×n1)