数据结构学习笔记【第5章 数组和广义表】
5.1 数组的定义
- n维数组
- n=1时,n维数组就退化为定长的线性表;反之,n维数组也可以看成是线性表的推广
- 数组一旦被定义,它的维数和维界就不再改变
- 除了结构的初始化和销毁之外,数组只有存取元素和修改元素值的操作
5.2 数组的顺序表示和实现
#include<stdio.h>
#include<stdlib.h>
#include<stdarg.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int Status;
typedef int ElemType;
#define MAX_ARRAY_DIM 8
typedef struct {
ElemType* base;
int dim;
int* bounds;
int* constants;
}Array;
Status InitArray(Array& A, int dim, ...);
Status DestroyArray(Array& A);
Status Locate(Array A, va_list ap, int& off);
Status Value(Array A, ElemType* e, ...);
Status Assign(Array& A, ElemType e, ...);
void print_Array(Array A);
int main()
{
Array A;
int dim = 2;
InitArray(A, dim, 2, 3);
Assign(A, 1, 0, 0);
Assign(A, 2, 0, 1);
Assign(A, 3, 0, 2);
Assign(A, 4, 1, 0);
Assign(A, 5, 1, 1);
Assign(A, 6, 1, 2);
print_Array(A);
ElemType e;
Value(A, &e, 0, 0);
printf("e:%d", e);
DestroyArray(A);
system("pause");
return 0;
}
Status InitArray(Array& A, int dim, ...)
{
if (dim<1 || dim>MAX_ARRAY_DIM)return ERROR;
A.dim = dim;
A.bounds = (int*)malloc(dim * sizeof(int));
if (!A.bounds)exit(OVERFLOW);
int elemtotal = 1;
va_list ap;
va_start(ap, dim);
int i;
for (i = 0; i < dim; i++) {
A.bounds[i] = va_arg(ap, int);
if (A.bounds[i] < 0)return ERROR;
elemtotal *= A.bounds[i];
}
va_end(ap);
A.base = (ElemType*)malloc(elemtotal * sizeof(ElemType));
if (!A.base)exit(OVERFLOW);
A.constants = (int*)malloc(dim * sizeof(int));
if (!A.constants)exit(OVERFLOW);
A.constants[dim - 1] = 1;
for (i = dim - 2; i >= 0; i--) {
A.constants[i] = A.bounds[i + 1] * A.constants[i + 1];
}
return OK;
}
Status DestroyArray(Array& A)
{
if (!A.base)return ERROR;
free(A.base); A.base = NULL;
if (!A.bounds)return ERROR;
free(A.bounds); A.bounds = NULL;
if (!A.constants)return ERROR;
free(A.constants); A.constants = NULL;
return OK;
}
Status Locate(Array A, va_list ap, int& off)
{
off = 0;
int i;
int ind;
for (i = 0; i < A.dim; i++)
{
ind = va_arg(ap, int);
if (ind < 0 || ind >= A.bounds[i])return OVERFLOW;
off += A.constants[i] * ind;
}
return OK;
}
Status Value(Array A, ElemType* e,...)
{
va_list ap;
int result;
int off;
va_start(ap, e);
if ((result = Locate(A, ap, off)) <= 0)return result;
*e = *(A.base + off);
va_end(ap);
return OK;
}
Status Assign(Array& A, ElemType e, ...)
{
va_list ap;
int result;
int off;
va_start(ap, e);
if ((result = Locate(A, ap, off)) <= 0)return result;
*(A.base + off) = e;
va_end(ap);
return OK;
}
void print_Array(Array A)
{
printf("Array:\n");
if (!A.base) {
printf("NULL\n");
}
int i, elemtotal=1;
for (i = 0; i < A.dim; i++)
{
elemtotal *= A.bounds[i];
}
for (i = 0; i < elemtotal; i++)
{
printf("%d ", A.base[i]);
if ((i + 1) % A.constants[0] == 0)
{
printf("\n");
}
}
}
5.3 矩阵的压缩存储
- 压缩存储:为多个值相同的元只分配一个存储空间,对零元不分配空间
- 特殊矩阵:值相同的元素或零元素在矩阵中的分布有一定规律,反之称为稀疏矩阵
5.3.1 特殊矩阵
- n阶对称矩阵
为每一对对称元分配一个存储空间,则可将
n2个元压缩存储到
2n(n+1)个元的空间中
- 对角矩阵
除了主对角线上和直接在对角线上、下方若干条对角线上的元之外,所有的其他的元均为零
5.3.2 稀疏矩阵
- 稀疏因子
假设在
m×n的矩阵中,有
t个元素不为零,令
δ=m×nt,称
δ为矩阵的稀疏因子
- 存储方式:除了存储非零元的值之外,还必须同时记下它所在行和列的位置
(i,j)。反之,一个三元组
(i,j,a)唯一确定了矩阵
A的一个非零元
- 算法5.1 采用三元组表存储表示,求稀疏矩阵M的转置矩阵T
时间复杂度
O(nu⋅tu),一般矩阵转置时间复杂度为
O(mu⋅nu),当
tu=mu×nu时,算法5.1的时间复杂度就为
O(mu⋅nu2)了,因此该算法仅使用于
tu≪mu×nu的情况
Status TransposeSMatrix(TSMatrix M, TSMatrix& T)
{
T.mu = M.nu; T.nu = M.mu; T.tu = M.tu;
if (T.nu)
{
int q = 1;
int col;
for (col = 1; col <= M.nu; col++)
{
int p;
for (p = 1; p <= M.tu; p++)
{
if (M.data[p].j == col)
{
T.data[q].i = M.data[p].j;
T.data[q].j = M.data[p].i;
T.data[q].e = M.data[p].e;
q++;
}
}
}
}
return OK;
}
- 算法5.2 采用三元组顺序表存储表示,求稀疏矩阵M的转置矩阵
T
- 按照
a.data中三元组的次序进行转置,并将转置后的三元组置入
b中恰当。的位置预先确定矩阵
M中每一列(即
T中每一行)的第一个非零元在
b.data中应有的位置
- 附设
num和
cpot两个向量。
num[col]表示矩阵
M中第
col列中非零元个数,
cpot[col]指示
M中第
col列的第一个非零元在
b.data中的恰当位置
- 时间复杂度
O(nu+tu)
Status FastTransposeSMatrix(TSMatrix M, TSMatrix& T)
{
T.mu = M.nu; T.nu = M.mu; T.tu = M.tu;
int col;
int num[MAXCOL + 1];
int cpot[MAXCOL + 1];
if (T.tu)
{
for (col = 1; col <= M.nu; col++)
{
num[col] = 0;
}
int t;
for (t = 1; t <= M.nu; t++) {
num[M.data[t].j]++;
}
cpot[1] = 1;
for (col = 2; col <= M.nu; col++)
{
cpot[col] = cpot[col - 1] + num[col - 1];
}
int p, q;
for (p = 1; p < M.tu; p++)
{
col = M.data[p].j;
q = cpot[col];
T.data[q].i = M.data[p].j; T.data[q].j = M.data[p].i;
T.data[q].e = M.data[p].e;
cpot[col]++;
}
}
return OK;
}
#include<stdio.h>
#include<stdlib.h>
#include<stdarg.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int Status;
typedef int ElemType;
#define MAXSIZE 12500
#define MAXCOL 100
typedef struct {
int i, j;
ElemType e;
}Triple;
typedef struct {
Triple data[MAXSIZE + 1];
int mu, nu, tu;
}TSMatrix;
Status TransposeSMatrix(TSMatrix M, TSMatrix& T);
Status FastTransposeSMatrix(TSMatrix M, TSMatrix& T);
int main()
{
system("pause");
return 0;
}
Status TransposeSMatrix(TSMatrix M, TSMatrix& T)
{
T.mu = M.nu; T.nu = M.mu; T.tu = M.tu;
if (T.nu)
{
int q = 1;
int col;
for (col = 1; col <= M.nu; col++)
{
int p;
for (p = 1; p <= M.tu; p++)
{
if (M.data[p].j == col)
{
T.data[q].i = M.data[p].j;
T.data[q].j = M.data[p].i;
T.data[q].e = M.data[p].e;
q++;
}
}
}
}
return OK;
}
Status FastTransposeSMatrix(TSMatrix M, TSMatrix& T)
{
T.mu = M.nu; T.nu = M.mu; T.tu = M.tu;
int col;
int num[MAXCOL + 1];
int cpot[MAXCOL + 1];
if (T.tu)
{
for (col = 1; col <= M.nu; col++)
{
num[col] = 0;
}
int t;
for (t = 1; t <= M.nu; t++) {
num[M.data[t].j]++;
}
cpot[1] = 1;
for (col = 2; col <= M.nu; col++)
{
cpot[col] = cpot[col - 1] + num[col - 1];
}
int p, q;
for (p = 1; p < M.tu; p++)
{
col = M.data[p].j;
q = cpot[col];
T.data[q].i = M.data[p].j; T.data[q].j = M.data[p].i;
T.data[q].e = M.data[p].e;
cpot[col]++;
}
}
return OK;
}
5.4 广义表的定义
- 广义表是线性表的推广,也称列表
- 广义表中可包含单个元素(原子)也可包含广义表(子表)
- 3个结论
列表的元素可以是子表
列表可为其他列表所共享
列表可以是一个递归的表,即列表也可以是其本身的一个子表
5.5 广义表的存储结构
- 由于广义表中数据元素可以具有不同的结构,因此难以用顺序存储结构表示,通常采用链式存储结构
- 一个表节点由3个域组成:标志域、指示表头的指针域和指示表尾的指针域
- 原子节点由2个域组成:标志域和值域
- 广义表的头尾链表存储表示
typedef enum { ATOM, LIST }ElemTag;
typedef struct GLNode {
ElemTag tag;
union {
AtomType atom;
struct { struct GLNode* hp, * tp; }ptr;
};
}*GList;
- 广义表的扩展线性链表存储表示
typedef enum { ATOM, LIST }ElemTag;
typedef struct GLNode {
ElemTag tag;
union {
AtomType atom;
struct GLNode* hp;
};
struct GLNode* tp;
}*GList;
5.6 m元多项式的表示
5.7 广义表的递归算法