数组的顺序存储表示和实现
数组的顺序存储结构:
![](https://img-blog.csdnimg.cn/2020032416135792.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQyMTg1OTk5,size_16,color_FFFFFF,t_70)
A[3][4][2]数组的存储结构:
![](https://img-blog.csdnimg.cn/20200324161509121.png)
如果要实现的是两维数组,参数中要包括两维的 长度,两个整型量;而如果是三维数组,则参数中要包括三维的长度,三个整型量。随着 所构造的数组的维数不同,参数的个数也不同。这就必须使用变长参数表才能解决参数个 数不定的问题。因此有些函数的形参有“...”,它代表变长参数表,即“...”可用若干个实参取代。这很适合含有维数不定的数组的函数。
va_list:用来保存宏va_start、va_arg和va_end所需信息的一种类型。为了访问变长参数列表中的参数,必须声明
va_list类型的一个对象
va_start:访问变长参数列表中的参数之前使用的宏,它初始化用va_list声明的对象,初始化结果供宏va_arg和
va_end使用;
va_arg: 展开成一个表达式的宏,该表达式具有变长参数列表中下一个参数的值和类型。每次调用va_arg都会修改
用va_list声明的对象,从而使该对象指向参数列表中的下一个参数;
va_end:该宏使程序能够从变长参数列表用宏va_start引用的函数中正常返回。
va在这里是variable-argument(可变参数)的意思.
typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef int Boolean; /* Boolean是布尔类型,其值是TRUE或FALSE */
typedef int ElemType;
#include<malloc.h> /* malloc()等 */
#include<stdio.h> /* EOF(=^Z或F6),NULL */
#include<process.h> /* exit() */
#include<math.h>
#include<stdarg.h> > // 实现变长参数表要包括的头文件,提供宏va_start,va_arg和va_end, */
/* 用于存取变长参数表 */
/* 函数结果状态代码 */
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
/* --------------------------- 数组的顺序存储表示 ------------------------------*/
#define MAX_ARRAY_DIM 8 /* 假设数组维数的最大值为8 */
typedef struct
{
ElemType *base; /* 数组元素基址,由InitArray分配 */
int dim; /* 数组维数 */
int *bounds; /* 数组维界基址,由InitArray分配 */
int *constants; /* 数组映象函数常量基址,由InitArray分配 */
}Array;
/* ------------------------------------------------------------------------------------------*/
/* --------------------------- 顺序存储数组的基本操作(5个) --------------------------*/
Status InitArray(Array *A, int dim, ...) // ...表示变长参数表,位于形参表的最后,前面必须至少有一个固定参数
{ /* 若维数dim和各维长度合法,则构造相应的数组A,并返回OK */
int elemtotal = 1, i; /* elemtotal是元素总值 */
va_list ap; // 定义ap是变长参数表类型(C语言的数据类型)
if (dim<1 || dim>MAX_ARRAY_DIM)
return ERROR;
(*A).dim = dim;
(*A).bounds = (int *)malloc(dim * sizeof(int));
if (!(*A).bounds)
exit(OVERFLOW);
va_start(ap, dim); // ap指向固定参数dim后面的实参表
for (i = 0; i < dim; ++i)
{
(*A).bounds[i] = va_arg(ap, int); //依次读取ap所指的实参(以逗号为分隔符)作为int类型实参,ap向后移
if ((*A).bounds[i] < 0)
return UNDERFLOW; /* 在math.h中定义为4 */
elemtotal *= (*A).bounds[i];
}
va_end(ap); // 与va_start()配对,结束对变长参数表的读取,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)
{ /* 销毁数组A */
if ((*A).base)
{
free((*A).base);
(*A).base = NULL;
}
else
return ERROR;
if ((*A).bounds)
{
free((*A).bounds);
(*A).bounds = NULL;
}
else
return ERROR;
if ((*A).constants)
{
free((*A).constants);
(*A).constants = NULL;
}
else
return ERROR;
return OK;
}
Status Locate(Array A, va_list ap, int *off) /* Value()、Assign()调用此函数 */
{ /* 若ap指示的各下标值合法,则求出该元素在A中的相对地址off */
int i, ind;
*off = 0;
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(ElemType *e, Array A, ...) /* 在VC++中,...之前的形参不能是引用类型 */
{ /* ...依次为各维的下标值,若各下标合法,则e被赋值为A的相应的元素值 */
va_list ap;
Status result;
int off;
va_start(ap, A);
if ((result = Locate(A, ap, &off)) == OVERFLOW) /* 调用Locate() */
return result;
*e = *(A.base + off);
return OK;
}
Status Assign(Array *A, ElemType e, ...)
{ /* ...依次为各维的下标值,若各下标合法,则将e的值赋给A的指定的元素 */
va_list ap;
Status result;
int off;
va_start(ap, e);
if ((result = Locate(*A, ap, &off)) == OVERFLOW) /* 调用Locate() */
return result;
*((*A).base + off) = e;
return OK;
}
/* ------------------------------------------------------------------------------------------*/
/* 检验以上操作的主程序 */
void main()
{
Array A;
int i, j, k, *p, dim = 3, bound1 = 3, bound2 = 4, bound3 = 2; /* a[3][4][2]数组 */
ElemType e, *p1;
InitArray(&A, dim, bound1, bound2, bound3); /* 构造3*4*2的3维数组A */
p = A.bounds;
printf("A.bounds=");
for (i = 0; i < dim; i++) /* 顺序输出A.bounds */
printf("%d ", *(p + i));
p = A.constants;
printf("\nA.constants=");
for (i = 0; i < dim; i++) /* 顺序输出A.constants */
printf("%d ", *(p + i));
printf("\n%d页%d行%d列矩阵元素如下:\n", bound1, bound2, bound3);
for (i = 0; i < bound1; i++)
{
for (j = 0; j < bound2; j++)
{
for (k = 0; k < bound3; k++)
{
Assign(&A, i * 100 + j * 10 + k, i, j, k); /* 将i*100+j*10+k赋值给A[i][j][k] */
Value(&e, A, i, j, k); /* 将A[i][j][k]的值赋给e */
printf("A[%d][%d][%d]=%2d ", i, j, k, e); /* 输出A[i][j][k] */
}
printf("\n");
}
printf("\n");
}
p1 = A.base;
printf("A.base=\n");
for (i = 0; i < bound1*bound2*bound3; i++) /* 顺序输出A.base */
{
printf("%4d", *(p1 + i));
if (i % (bound2*bound3) == bound2 * bound3 - 1)
printf("\n");
}
DestroyArray(&A);
}
运行结果: