文章目录
4.1 定义
数组与广义表可看做一种扩展的线性数据结构其特殊性反映在数据元素的构成上。从组成线性表的元素角度看,数组是由具有某种结构的数据元素构成,广义表则是由单个元素或子表构成的。即数组和广义表中的数据元素可以是单个元素,也可以是一个具有线性结构的数据。
4.2 数组的顺序存储与实现
1.一维数组的地址计算:设一维数组A=a1,a2,…an,数组中每个元素占size单元,则ai的地址:
l
o
c
(
a
1
)
+
s
i
z
e
∗
(
i
−
1
)
loc(a_1)+size\ast(i-1)
loc(a1)+size∗(i−1)
2.二维数组的地址计算:Am×n按以行为主存储,下标从1开始,
l
o
c
(
a
i
j
)
=
l
o
c
(
a
11
)
+
s
i
z
e
∗
(
n
∗
(
i
−
1
)
+
j
−
1
)
loc(a_{ij})=loc(a_{11})+size\ast(n\ast(i-1)+j-1)
loc(aij)=loc(a11)+size∗(n∗(i−1)+j−1)
3.三维数组的地址计算:Ar×m×n以按行为主存储,下标从1开始,
l
o
c
(
a
i
j
k
)
=
l
o
c
(
a
111
)
+
s
i
z
e
∗
(
(
i
−
1
)
∗
m
∗
n
+
(
j
−
1
)
∗
n
+
(
k
−
1
)
)
loc(a_{ijk})=loc(a~_{111})+size\ast((i-1)\ast m\ast n+(j-1)\ast n+(k-1))
loc(aijk)=loc(a 111)+size∗((i−1)∗m∗n+(j−1)∗n+(k−1))
4.n维数组的地址计算:A[c_1…d_1,c_2…d_2,…c_n…d_n],按行为主存储,
l
o
c
(
j
1
,
j
2
,
.
.
.
,
j
n
)
=
l
o
c
(
c
1
,
c
2
,
.
.
.
,
c
n
)
+
∑
i
=
1
n
α
i
∗
(
j
i
−
c
i
)
loc(j_1,j_2,...,j_n)=loc(c_1,c_2,...,c_n)+\sum_{i=1}^{n}\alpha_i\ast(j_i-c_i)
loc(j1,j2,...,jn)=loc(c1,c2,...,cn)+∑i=1nαi∗(ji−ci)
4.3 特殊矩阵的压缩存储
4.3.1 规律分布的特殊矩阵
1.三角矩阵
以下三角矩阵为例:只存非零元素,即存储到一个大小为n×(n-1)/2的一维数组中:
l
o
c
[
i
,
j
]
=
l
o
c
[
1
,
1
]
+
s
i
z
e
∗
(
i
∗
(
i
−
1
)
/
2
+
j
−
1
)
loc[i,j]=loc[1,1]+size\ast(i\ast (i-1)/2+j-1)
loc[i,j]=loc[1,1]+size∗(i∗(i−1)/2+j−1).
2.带状矩阵:
以三对角带状矩阵为例:只存非零元素,即存储到一个大小为3n-2的一维数组中:
l
o
c
[
i
,
j
]
=
l
o
c
[
1
,
1
]
+
s
i
z
e
∗
(
2
(
i
−
1
)
+
j
−
1
)
loc[i,j]=loc[1,1]+size\ast(2(i-1)+j-1)
loc[i,j]=loc[1,1]+size∗(2(i−1)+j−1).
4.3.2 非零元素很少的稀疏矩阵
1.稀疏矩阵的三元组表表示法
//类型定义
#define MAXSIZE 500
typedef int ElemType;
typedef struct
{
int row,col;
ElemType e;
}Triple;
typedef struct
{
Triple data[MAXSIZE];
int m,n,len;
}TSMatrix;
2.稀疏矩阵的链式存储结构——十字链表
能够灵活地插入因运算而产生的新的非零元素,实现矩阵的各种运算。
//类型定义
typedef struct OLNode
{
int row,col;
ElemType value;
struct OLNode * right,*down;
}OLNode,*OLink;
typedef struct
{
OLink *row_head,*col_head;
int m,n,len;
}CrossList;
4.4 矩阵的转置
4.4.1 经典算法
void TransMatrix(ElemType source[m][n],ElemType dest[n][m])
{
int i,j;
for(i=0;i<m;i++)
for(j=0;j<n;j++)
dest[j][i]=source[i][j];
}
4.4.2 用三元组表实现稀疏矩阵的转置
1.列序递增转置法
//简单转置
void TransposeTSMatrix(TSMatrix A,TSMatrix &B)
{
IniArray(B);
int i,j,k=1;
B.m=A.n;
B.n=A.m;
B.len=A.len;
for(i=1;i<=A.n;i++)
{
for(j=1;j<=A.len;j++)
{
if(A.data[j].col==i)
{
B.data[k].row=A.data[j].col;
B.data[k].col=A.data[j].row;
B.data[k].e=A.data[j].e;
j++,k++;
}
}
}
}
2.一次定位快速转置法
需要预先计算以下数据:
1).待转置矩阵三元组表A每一列中非零元素的总个数num[]
2).待转置矩阵每一列中第一个非零元素在三元组表B中的位置position[]
//快速转置
void FastTransposeTSMatrix(TSMatrix A,TSMatrix &B)
{
IniArray(B);
int col,i,p,q;
int num[MAXSIZE],position[MAXSIZE];
B.len=A.len,B.m=A.n,B.n=A.m;
if(B.len)
{
for(col=1;col<=A.n;col++)
{
num[col]=0;
}
for(i=1;i<=A.len;i++)
{
num[A.data[i].col]++;
}
position[1]=1;
for(col=2;col<=A.n;col++)
{
position[col]=position[col-1]+num[col-1];
}
for(p=1;p<=A.len;p++)
{
col=A.data[p].col,q=position[col];
B.data[q].col=A.data[p].row;
B.data[q].row=A.data[p].col;
B.data[q].e=A.data[p].e;
position[col]++;
}
}
}
4.4.3 十字链表
//建立十字链表
int CreateCrossList(CrossList * M)
{
int m,n,t,i,j;
ElemType e;
OLNode* p,*q;
scanf("%d %d %d",&m,&n,&t);//读入行数列数和非零元素个数
M->m=m,M->n=n,M->len=t;
if(!(M->row_head=(OLink*)malloc((m+1)*sizeof(OLink)))) return 0;
if(!(M->col_head=(OLink*)malloc((n+1)*sizeof(OLink)))) return 0;
M->row_head=M->col_head=NULL;
scanf("%d %d %d",&i,&j,&e);
while(i!=0)
{
if(!(p=(OLink)malloc(sizeof(OLNode)))) return 0;
p->row=i,p->col=j,p->value=e;
if(M->row_head[i]==NULL) M->row_head[i]=p;
else{
/*寻找行表中的插入位置*/
q=M->row_head[i];
while(q->right!=NULL&& q->right->col<j)
q=q->right;
p->right=q->right,q->right=p;
}
if(M->col_head[j]==NULL) M->col_head[j]=p;
else{
/*寻找列表中的插入位置*/
q=M->col_head[j];
while(q->down!=NULL&& q->down->row<i)
q=q->down;
p->down=q->down,q->down=p;
}
scanf("%d %d %d",&i,&j,&e);
}
}
4.5 广义表
4.5.1 存储结构
1.头尾链表存储结构
typedef char AtomType;
typedef enum{ATOM,LIST} ElemTag;
typedef struct GLNode
{
ElemTag tag;
union
{
AtomType atom;
struct{struct GLNode* hp,*tp;
}htp;
}atom_htp;
}GLNode,*GList;
2.同层结点链存储结构
typedef char AtomType;
typedef enum{ATOM,LIST} ElemTag;
typedef struct GLNode
{
ElemTag tag;
union
{
AtomType atom;
struct GLNode* hp;
}atom_hp;
struct GLNode* tp;
}GLNode,*GList;
4.5.2 操作实现
以头尾链表存储结构为例
typedef char AtomType;
typedef enum{ATOM,LIST} ElemTag;
typedef struct GLNode
{
ElemTag tag;
union
{
AtomType atom;
struct{struct GLNode* hp,*tp;
}htp;
}atom_htp;
}GLNode,*GList;
GList Head(GList L)//求广义表L的表头
{
if(L==NULL) return (NULL);//空表无表头
if(L->tag==ATOM) exit(0);//原子不是表
else return(L->atom_htp.htp.hp);
}
GList Tail(GList L)//求广义表L的表尾
{
if(L==NULL) return(NULL);
if(L->tag==ATOM) exit(0);
else return(L->atom_htp.htp.tp);
}
int Length(GList L)//求广义表的长度
{
int k=0;
GLNode *s;
if(L==NULL) return 0;
if(L->tag==ATOM) exit(0);
s=L;
while(s!=NULL)
{
k++;
s=s->atom_htp.htp.tp;
}
return k;
}
int Depth(GList L)//求广义表的深度
{
int d,max;
GLNode *s;
if(L==NULL) return 1;
if(L->tag==ATOM) return 0;
s=L;
while(s!=NULL)
{
d=Depth(s->atom_htp.htp.hp);
if(d>max) max=d;
s=s->atom_htp.htp.tp;
}
return (max+1);
}
int CountAtom(GList L)//统计广义表中原子数目
{
int n1,n2;
if(L==NULL) return 0;
if(L->tag==ATOM) return 1;
n1=CountAtom(L->atom_htp.htp.hp);
n2=CountAtom(L->atom_htp.htp.tp);
return (n1+n2);
}
int CopyGList(GList S,GList * T)//复制广义表
{
if(S==NULL)
{
*T=NULL;
return 1;
}
*T=(GLNode *)malloc(sizeof(GLNode));
if(S->tag==ATOM) (*T)->atom_htp.atom=S->atom_htp.atom;
else{
CopyGList(S->atom_htp.htp.hp,&((*T)->atom_htp.htp.hp));
CopyGList(S->atom_htp.htp.tp,&((*T)->atom_htp.htp.tp));
}
return 1;
}