一、数组
1.ADT
n个相同类型的数据元素构成的有限序列。每个数据元素成为一个数组元素,每个元素在n给线性关系中的序号成为该元素的下标,下标的取值范围称为数组的维
N维数组中的每个元素都受N个线性关系的约束
- 初始化操作 InitArray(&A,n,bound1,…,boundn)
- 销毁操作 DestroyArray(&A)
- 读元素操作 Value(A,&e,index1,…,indexn)
- 写元素操作 Assign(&A,e,index1,…,indexn)
2.数组的存储结构与寻址
(1)一维数组
设具有M个元素的一维数组的下标范围为闭区间 [0, M-1],每个数组元素占用 L 个存储单元。
ai 的存储地址:Loc( ai )=Loc(a0)+i×L
(2)二维数组
逻辑上是二维的,存储是一维的,有两种映射方式
按行优先:先行后列,先存储行号较小的元素,行号相同者先存储列号较小的元素。
Loc(aij) = Loc(a00)+( N×i+j )×L
按列优先:先列后行,先存储列号较小的元素,列号相同者先存储行号较小的元素。
Loc(aij) = Loc(a00)+( N×j+i )×L
(3)n维数组
Loc( j1, j2, …, jn )= Loc(0, 0, …, 0) + ( b2×b3×... ×bn×j1+ b3×...×bn×j2+ ...+ bn×jn-1 + jn ) L
= Loc(0, 0, …, 0) + ∑ci ji
cn=L,ci-1 =bi×ci,1< i ≤ n。
二、矩阵的压缩存储
1.特殊矩阵
(1)对称矩阵
用一维数组,按行优先存储下三角元素。
(2)下三角矩阵
(3)上三角矩阵
2.稀疏矩阵
假设 m 行 n 列的矩阵,其中非零元素(t 个)比例小于5%的矩阵为稀疏矩阵。
即,稀疏因子的矩阵为稀疏矩阵。
- 三元组顺序表
- 行逻辑链接顺序表
- 十字链表
(1)三元组(行, 列, 值)
#define MAXSIZE 12500
typedef struct {
int i,j; // 非零元的行下标和列下标
ElemType e; // 非零元值
} Triple;
typedef struct {
Triple data [ MAXSIZE+1 ];
// 用于存储三元组表, data[0]未用
int mu,nu,tu; // 行数、列数和非零元个数
} TSMatrix;
(2)行逻辑链接顺序表
#define MAXSIZE 12500
#define MAXSMN 500
typedef struct {
int i,j; // 非零元的行下标和列下标
ElemType e; // 非零元值
} Triple;
typedef struct {
Triple data[ MAXSIZE+1 ];
int rpos[MAXMN+1];
// 每行第一个元素的位置表
int mu, nu, tu;
} RLSMatrix;
(3)十字链表
typedef struct OLNode {
int row, col; // 非零元的行下标和列下标
ElemType e; // 非零元值
struct OLNode * right, * down
} OLNode, *OLink;
typedef struct {
OLink *rhead,*chead; // 行/列表头指针数组
int mu, nu, tu; // 行数、列数和非零元个数
} CrossList;
3.应用
(1)矩阵的快速转置算法
#define MAXSIZE 12500
typedef struct {
int i, j; // 非零元的行下标和列下标
int e; // 非零元值
} Triple;
typedef struct {
Triple data[MAXSIZE + 1];
// 用于存储三元组表, data[0]未用
int mu, nu, tu; // 行数、列数和非零元个数
} TSMatrix;
bool FastTransMatrix(TSMatrix M, TSMatrix &T) {
T.mu = M.nu;
T.nu = M.mu;
T.tu = M.tu;
if (T.tu) {
int num[MAXSIZE]; //存储M第 col 列非零元个数
int cpos[MAXSIZE]; //存储M第 col 列第一个非零元在T.data 中的位置
for (int col = 1; col <= M.nu; col++) {
num[col] = 0;
}
for (int t = 1; t < T.tu; t++) {
num[M.data[t].j]++;
}
cpos[1] = 1;
for (int col = 2; col <= M.nu; col++) {
cpos[col] = cpos[col - 1] + num[col - 1];
}
for (int t = 0; t < T.tu; t++) {
int col = M.data[t].j;
int pos = cpos[col];
T.data[pos].i = M.data[t].j;
T.data[pos].j = M.data[t].i;
T.data[pos].e = M.data[t].e;
cpos[col]++;
}
//时间复杂度O(nu+tu)
}
return true;
}
(2)稀疏矩阵的乘法
#define MAXSIZE 12500
#define MAXMN 500
typedef struct {
int i, j; // 非零元的行下标和列下标
int e; // 非零元值
} Triple;
typedef struct {
Triple data[MAXSIZE + 1];
int rpos[MAXMN + 1];
// 每行第一个元素的位置表
int mu, nu, tu; // 行数、列数和非零元个数
} RTSMatrix;
bool MatrixMultiplication(RTSMatrix M, RTSMatrix N, RTSMatrix &A) {
if (M.nu != N.mu) return false;
A.mu = M.mu;
A.nu = N.nu;
A.tu = 0;
if (M.tu*N.tu != 0) {
int temp[MAXMN];
for (int rowM = 1; rowM <= M.mu; rowM++) {
for (int colM = 1; colM <= M.nu; colM++) {
temp[colM] = 0; //清0
}
A.rpos[rowM] = A.tu + 1;
int nextrposM; //M矩阵的元素的下一行非零元素在顺序表中的位置
if (rowM < M.mu) {
nextrposM = M.rpos[rowM + 1];
}
else {
nextrposM = M.tu + 1;
}
//遍历M中第row行的所有元素
for (int rposM = M.rpos[rowM]; rposM < nextrposM; rposM++) {
int rowN = M.data[rposM].j;
int nextrposN;
if (rowN < N.mu) {
nextrposN = N.rpos[rowN + 1];
}
else {
nextrposN = N.tu + 1;
}
int rposN;
//遍历N中第col行的所有元素,一次计算一行
for (rposN = N.rpos[rowN]; rposN < nextrposN; rposN++) {
int col = N.data[rposN].j;
temp[col] += M.data[rposM].e*N.data[rposN].e;
}
}
for (int col = 1; col <= A.nu; col++) {
if (temp[col] != 0) {
A.tu++;
if (A.tu > MAXSIZE) {
return false;
}
A.data[A.tu] = { rowM,col,temp[col] };
}
}
}
}
return true;
}
三、广义表
1.ADT
广义表(lists)是一种不同构的线性结构, LS = ( a1, a2, ... ,an)其中ai或为原子(atom) 或为广义表。
广义表是递归定义
广义表中的元素既可以是单个元素(原子atom),也可以是广义表(子表sublist),当每个元素均为原子且类型相同时,就是线性表。
表头:LS的第一个元素称为表头
表尾:其余元素组成的表称为LS的表尾
表长:最外层包含元素个数
深度:所含括号的重数。原子的深度为 0,空表的深度为 1。
InitGList(&L);
DestroyGList(&L);
CreateGList(&L, S);
CopyGList(&T, L);
GListLength(L);
GListDepth(L);
GListEmpty(L);
GetHead(L);
GetTail(L);
InsertFirst_GL(&L, e);
DeleteFirst_GL(&L, &e);
Traverse_GL(L, Visit());
typedef struct Node
{
int tag;//0表示原子,1表示表
char atom;
struct Node *hp;//指向子表
struct Node *tp;//指向下一个节点
}GLNode;
GLNode* CreatList(char* &str)
{
Node *head = new Node;
GLNode* p = head;
p->hp = NULL;
p->tp = NULL;
p->atom = '\0';
p->tag = -1;
++str;
while (*str)
{
if (*str >= 'a'&&*str <= 'z')
{
p->tag = 0;
p->atom = *str;
p->tp = new Node;
p = p->tp;
p->hp = NULL;
p->tp = NULL;
p->atom = '\0';
p->tag = -1;
++str;
}
else if (*str == '(')
{
p->tag = 1;
p->hp = new Node;
p->hp = CreatList(str);
p->tp = new Node;
p = p->tp;
p->hp = NULL;
p->tp = NULL;
p->atom = '\0';
p->tag = -1;
++str;
}
else if (*str == ')')
{
flll = 1;
p = NULL;
return head;
}
else
{
++str;
}
}
return head;
}
GLNode* GetHead(GLNode* L)
{
GLNode* head;
if (L->tag == 0)
{
head = L;
head->tp = NULL;
return head;
}
else if (L->tag == 1)
{
head = L;
head = L->hp;
return head;
}
else
{
printf("error.\n");
}
}
GLNode* GetTail(GLNode* L)
{
GLNode* tail;
tail = L->tp;
return tail;
}
void output(GLNode* L)
{
if (L->tp == NULL && L->hp == NULL && L->atom != '0'&&L->tag != -1)
{
printf("%c", L->atom);
flag = 1;
}
else
{
printf("(");
GLNode* p = L;
while (p)
{
if (p->tag == 0)
{
printf("%c", p->atom);
flah++;
p = p->tp;
}
else if (p->tag == 1)
{
output(p->hp);
p = p->tp;
}
if (p->tag == 0 || p->tag == 1)
{
printf(",");
}
else
{
break;
}
}
flah++;
printf(")");
}
}
int main()
{
char *str;
char strr[500];
int choose;
scanf("%s", strr);
str = strr;
GLNode* L = new Node;
L = CreatList(str);
printf("generic list: ");
output(L);
printf("\n");
while (1)
{
scanf("%d", &choose);
if (choose == 1)
{
printf("destroy tail\n");
printf("free list node\n");
L = GetHead(L);
printf("generic list: ");
output(L);
printf("\n");
}
else if (choose == 2)
{
printf("free head node\n");
printf("free list node\n");
L = GetTail(L);
printf("generic list: ");
output(L);
printf("\n");
}
else
{
printf("error\n");
break;
}
if (flag == 1)
{
break;
}
if (flah == 1)
{
break;
}
else
{
flah = 0;
}
}
}
2.练习
(1)
A = ( ) 空表 表长0,深度1
B = ( b, c, d ) 表头b,表尾(c,d),深度1,表长3
C = ( a, B ) = ( a, (b,c,d) ) 表头a,表尾(B),深度2,表长2
D = ( A, B, C ) = ( ( ), (b,c,d), (a,(b,c,d)) )表头(),表尾(B,C),表长3,深度3
(2)
D = ( E, F ) = ( ( a, ( b, c ) ),F )
Head( D ) = E
Tail( D ) = (F)
Head( E ) = a
Tail( E )= ((b,c))
Head( ((b, c)) ) = (b,c)
Tail( ((b, c)) ) = ()
Head( (b, c) ) =b
Tail( (b, c) )=(c)
Head( ( c ) ) =c
Tail( ( c ) ) = ()