文章目录
数组
数组是一种特殊的线性表,线性表元素本身又是一个线性表
一、顺序存储
行序存储下aij储存位置为:
Loc(aij) = Loc(a11)+[(i-1)n + (j-1)]*L
列序存储下aij的存储位置为:
Loc(aij) = Loc(a11)+[(j-1)m + (i-1)]*L
二、压缩存储
一)特殊矩阵
1.对称矩阵
元素特性: aij = aji
存储空间:n(n+1)/2
存储位置:Loc(aij)=Loc(a11)+[i(i-1)/2+(j-1)]*L (i>j)
Loc(aij)=Loc(a11)+[j(j-1)/2+(i-1)]*L (j>i)
2.三角矩阵
元素特性:aij = 0 (i<j)
存储空间:n(n+1)/2
存储位置:Loc(aij)=Loc(a11)+[i(i-1)/2+(j-1)]*L (i>j)
3.对角矩阵
元素特性:aij = 0 (|i-j|>1)
存储空间:(n-2)*3+4 = 3n-2
存储位置:Loc(aij) = Loc(a11) + [(i-1)*2+j-1]*L
二)稀疏矩阵
1.定义
元素特性:非零元较少,分布无规律
存储原则:储存行列下标(三元组表)、矩阵维数
三元组结构
typedef struct
{ int i , j;
ELemType e ;//ELemType应该是预先定义的元素类型
}Tripe;
稀疏矩阵结构
#define MAXSIZE 100
typedef struct
{ Tripe data[MAXSIZE + 1];//data[0]不使用
int mu , nu ,tu;
}TSMatrix;
2.顺序压缩储存
顺序压缩储存之后,稀疏矩阵失去了随机存取的能力
问题:存取第i行第j列非零元
三元组表:从头查找
带行链接信息的三元组表:
增加一个数组 rpos[MaxRC+1]
(MaxRC
为行数,rpos[0]
不用)
rpos[i]
表示第i行第1个非零元在三元组表中的下标
伪地址表示法:
伪地址定义:行优先储存时,包括零元素在内的元素相对位置
2.转置
①直接转置
//m*n的矩阵
for(col=0;row<mu;col++)
{
for(row=0;row<mu;row++)
T[col][row]=M[row][col];
}
②三元组表法以M的列序转置
Status TransposeSMatrix(TSMatrix M,TSMATRIC &T)//希望在函数内部设置的三元组表通过引用方式进行返回
{ int col,p,k;
T.mu=M.nu;
T.nu=M.mu;
T.tu=M.tu;//赋予T矩阵行数、列数、元素个数
if(T.tu)
{ k=1;//k为T.data的下标
for(col=1;col<=M.nu;col++)//查找每一列的非零元
{
for(p=1;p<=M.tu;p++)//p是M.data的下标,用于遍历M三元组
{
if(M.data[p].j==col)//当M三元组中的某一元素中的列数与所求列数相同
{ T.data[k].i = M.data[p].j;
T.data[k].j = M.data[p].i;
T.data[k].e = M.data[p].e;
k++;//完成了T.data[k]位置的元素,前往下一个位置
}
}
}
return OK;
}
return ERROR;
}
算法时间复杂度 T(n) = O(M.nu*M.tu)
,若M.tu
与M.mu*M.nu
同一个数量级,则时间算法复杂度T(n)=O(M.mu*M.nu^2)
,与一般转置方法相比没有优势。
③快速转置
按M.data中三元组次序转置,结果直接找到T.data中正确位置。
void fast_transpos(TSMatrix M,TSMatrix &T)
{ int col,p,num[N],num[N];
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(p=1;p<=M.tu;col++)num[M.data[p].j]++;
cpot[0]=0;cpot[1]=1;
for(col=2;col<=M.nu;col++)
cpot[col]=cpot[col-1]+num[col-1];
for(p=1;p<=M.tu;p++)
{ col=M.data[p].j;k=cpot[col];
T.data[k].i=M.data[p].j;
T.data[k].j=M.data[p].i;
T.data[k].e=M.data[p].e;
cpot[col]++;
}
}
}
时间复杂度为T(n)=O(M.nu+M.tu)
,若M.tu
与M.mu*M.nu
同数量级,T(n)=O(M.mu*M.nu)
与直接转置数量相同,故在算法上有优越性。
3.链式压缩存储
如果要进行矩阵相加等运算,稀疏矩阵的非零元位置和个数都会发生变化。使用三元组表必然会引起数组元素的大量移动。
①带行指针向量的单链表表示
每行非零元用一个单链表储存,建立一个数组储存各行单链表的头指针。
typedef struct RLNode//单链表节点
{ int j;//列数
ElemType e;//节点元素
struct RLNode *right;//指向节点指针
}RLNide,*Rlink;//定义了一个被Rlink指针所指的对象
typedef struct
{ RLink rhead[M];//创建了一个指向RLNide结构体的指针数组
int mu,nu,tu;
}RowList;
②十字链表存储
非零元结点包含五个域(非零元所在行、列、值,指向同行同列的下一个非零元指针)
实际上就是两个单链表交叉
typedef struct OLNode//结点结构
{ int row,col;//所在行列
ElemType val;//非零元的值
struct OLNode *right,*down;//同行、同列的下一个非零元指针
}OLNode,*OLink;
typedef struct//十字链表结构
{ OLink rhead[M],chead[N];//行列指针数组
int mu,nu,tu;
}CrossList;