1、数组的定义:
数组:由一组名字相同,下表不同的标量构成
(注意:本章所讨论的数组与高级语言中的数组有所区别:高级语言中的数组的顺序结构;而本章的数组既可以顺序的,也可以是链式结构,用户可根据需要选择。)
2、数组的结构:
(1)数组中各元素具有统一的类型
(2)数组元素的下标一般具有固定的上界和下界,即数组一旦被定义,它的维数和维界就不再改变。
(3)数组的基本操作比较简单,除了结构的初始化和销毁之外,只有存取元素和修改元素值得操作
3、数组的特点
4、数组抽象数据a类型数组的定义:
ADT Array{
数据对象: ji=0,...,bi-1, i=1,2,...,n,
D ={ aj1 j2 ... jn | n(>0)成为数组的维数, bi 是数组第 i 维的长度 ,
ji 是数组元素的第 i 维下标, j1 j2 ... jn 属于 ELemSet }
数据关系: R={ R1, R2,... , Rn }
Ri={ < aj1... ji ... jn , aj1... ji+1 ... jn > |
0<= jk <= bk -1 ,1 <= k <=n 且 k!=i ,
0<= ji <= bi -2,
a j1 ... ji ... jn , aj1... ji+1 ... jn 属于 D ,i =2 ,... ,n }
基本操作:
InitArray( &A ,n,bound 1 ,..., bound n )
操作结果:若维数 n 和各维长度合法,则构造相应的数组 A ,并返回 OK。
DestroyArray( &A )
操作结果:销毁数组 A 。
Value( A ,&e , index1, ... , indexn)
初始条件:A是 n维数组,e 是元素变量 ,随后是 n 个下标值。
操作结果:若各下标不超界,则 e 赋值为所指定的 A 的元素值,并返回OK。
Assign( &A , e , index1, ... ,indexn )
初始条件:A是 n 维数组,e为元素变量,随后是 n 个下标值。
操作结果:若下标不超界,则将 e 的值赋给所所指定的A 的元素,并返回OK。
} ADT Array
5、代码实现:
----------------------------------------------------------------------------------------------------------------
#include<stdio.h>
#include<stdlib.h>
#include<stdarg.h> //标准头文件,提供宏 va_strat、va_arg 和 va_end,
//用于存取变长参数表
//宏定义
#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define UNDERFLOW -1
typedef int ElemType;
typedef int Status;
#define MAX_ARRAY_DIM 8 //假设数组维数的最大值为8
typedef struct{
ElemType *base; //数组元素基址,由InitArray分配
int dim; //数组维数
int *bounds; //数组维界基址,由InitArray分配
int *constants; //数组映像函数常量基址,由InitArray分配
}Array;
//-------基本操作说明---------
//1、构造数组A,并返回OK
//Status InitArray(Array &A,int dim,...)
//2、销毁数组 A
//Status DestroyArray(Array &A)
//3、若 ap 指示的各下标值合法,则求出该元素在A中相对地址 off
//Status Locate(Array A,va_list ap,int &off)
//4、A是n维数组,e是元素变量,随后是n个下标值
// 若各下标不超界,则 e 赋值为所指定的A的元素值,并返回 OK
// Status Value(Array A,ElemType &e, ...)
//5、将e的值赋给所指定的 A的元素值
//Status Assign(Array A,ElemType e,...)
//---------基本操作的算法描述-----------
//1、构造数组A,并返回OK
Status InitArray(Array &A,int dim,...){
//若维数 dim 和各维度长度合法,则构造相应的数组A,并返回OK
if( dim<1 || dim>MAX_ARRAY_DIM) return ERROR;
A.dim=dim;
A.bounds=(int *)malloc(dim*sizeof(int)); //开辟内存,并把基地址赋给A.bounds
if(!A.bounds) exit(OVERFLOW);; //分配存放“各维长度”的空间, 若维度长度合法,则存入 A.bounds,并求出A //的元素总数elemtotal
//若各维长合法,则存入 A.bounds ,并求出A的元素总数 elemtotal
int elemtotal=1; //存放元素总数
va_list ap; //存放变长参数表信息的数组
va_start(ap,dim); //ap为 va_list 类型,是存放变长参数表信息的数组 ,第二个参数是第一个可变参数的前一个参数,固定的
for(int i=0;i<dim;i++){
A.bounds[i]=va_arg(ap,int); //用va_arg返回可变参数,并赋值给整数 A.bounds[i] ,va_arg的第二个参数是要返回的类型
if(A.bounds[i]<0)
return UNDERFLOW;
elemtotal *=A.bounds[i];
}
va_end(ap);
A.base =(ElemType *)malloc(elemtotal *sizeof(ElemType));
if(!A.base) exit(OVERFLOW);
//求映像函数的常数 ci,并存入 A.constants[i], i=1,...,dim
A.constants=(int *)malloc(dim *sizeof(int));
if(!A.constants)
exit(OVERFLOW);
A.constants[dim-1]=1; //L=1,指针的增减以元素的大小为单位
for(i=dim-2;i>=0;i--)
A.constants[i]=A.bounds[i+1] * A.constants[i+1];
return OK;
}
//2、销毁数组 A
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); //映像函数 Ci 保存区指针
A.constants=NULL;
return OK;
}
//3、若 ap 指示的各下标值合法,则求出该元素在A中相对地址 off
Status Locate(Array A,va_list ap,int &off){
off=0;
int index;
for(int i=0;i<A.dim;i++){
index=va_arg(ap,int);
if(index<0||index>=A.bounds[i])
return OVERFLOW;
off+=A.constants[i] * index;
}
return OK;
}
//4、A是n维数组,e是元素变量,随后是n个下标值
// 若各下标不超界,则 e 赋值为所指定的A的元素值,并返回 OK
Status Value(const Array &A,ElemType *e, ...){
va_list ap;
va_start(ap, e);
int result;
int off;
if((result=Locate(A,ap,off))<=0)
return result;
*e=*(A.base+off);
return OK;
}
//5、A是n维数组,e为元素变量,随后是n个下标值
//若下标不超界,则将e的值赋给所指定的 A的元素值,并返回OK
Status Assign(Array A,ElemType e,...){
va_list ap;
va_start(ap,e);
int off;
int result;
if((result=Locate(A,ap,off))<=0)
return result;
*(A.base+off)=e;
va_end(ap);
return OK;
}
//----------主函数---------
void main(){
Array A;
int testArray[2][3] = {{1, 2, 3},{4, 5, 6}};
InitArray(A,2,2,3);
printf("A.dim=%d\n",A.dim);
printf("各维的长度是:\n");
for(int index=0 ;index<A.dim;index++){
printf("%d\t",A.bounds[index]);
}
printf("\n");
printf("数组的常量基址是\n");
for(index=0;index<A.dim;index++)
printf("%d\t",A.constants[index]);
printf("\n");
//对数组进行赋值
for(int i=0;i<2;i++)
for(int j=0;j<3;j++)
Assign(A,testArray[i][j],i,j);
int value;
printf("数组中的元素为:\n");
for(i=0;i<2;i++){
for(int j=0;j<3;j++)
{
Value(A,&value,i,j);
printf("%d \t",value);
}
printf("\n");
}
printf("按照数组的线性序列输出元素,即利用基址地址输出元素:\n");
for( i = 0; i < 2 * 3; i++)
{
printf("第%d个元素=%3d\t",i+1,A.base[i]);
if( (i+1) % 3 == 0 )
printf("\n");
}
}