第五章 数组和广义表(1)

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");  
     }  
}




  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值