相关定义

  • 前边讨论的线性表、串中的数据元素都是非结构的原子类型,即元素的值是不能再分解的;而数组和广义表中的数据元素本身也是数据结构,可以分解
  • 顺序存储的次序约定问题:
语言类型 排序方式 例子
C语言、PASCAL、拓展BASIC 以行序为主序,把每个高维数组的第一个先依次表示出来 a【0】【1】,a【1】【1】,a【2】【1】...
FORTARN 以列序为主序,把一个高维数组的所有元素先依次表示出来 a【0】【1】,a【0】【2】,a【0】【3】...
  • 数组一旦被定义,其维数和维界就不再改变,因此一般不做插入或删除操作,除初始化和销毁数组外,只有存取和修改元素的操作
  • 数组是可随机存取的数据结构:

(1)一旦规定维数和维界,便可以分配储存空间
(2)由下标对应便可取得相应元素的储存位置

需要用到知识(建议结合下边代码,更易理解)

  • <stdarg.h>头文件

stdarg.h 头文件定义了一个变量类型 va_list 和三个宏,这三个宏可获取参数数量可变的函数中的参数。可变参数的函数通在参数列表的末尾是使用省略号(,...)定义的。

类型 形式 描述 功能
变量类型 va_list 这是一个适用于 va_start()、va_arg()va_end() 这三个宏存储信息的类型。
void va_start(va_list ap, last_arg) 这个宏初始化 ap 变量。其中,last_arg 是最后一个传递给函数的已知的固定参数,即省略号之前的参数。 这个宏的功能就是:输入第n个参数,输出的就是第n + 1个参数的地址值。va_start(ap, e); va_start 是一个宏,展开后,实际上相当于 ap = (char*)&e + sizeof(e);
type va_arg(va_list ap, type) 这个宏检索函数参数列表中类型为 type 的下一个参数。 返回当前地址指向的值后,将地址加一T var = va_arg(ap, T); 这个相当于 两句话, T var = *(T*)ap; ap+= sizeof(T);
void va_end(va_list ap) 这个宏允许使用了 va_start 宏的带有可变参数的函数返回。如果在从函数返回之前没有调用 va_end,则结果为未定义。

数组的顺序表示与相关操作的实现

  • 数组的顺序表示
#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 Value(Array A, ElemType *e ,...);         
Status Assign(Array * A, ElemType e, ...);   
Status Locate( Array A ,va_list ap,int *begin);//若ap指示的各下标值合法,则求出该元素在A中的相对地址begin
  • 初始化数组
Status InitArray(Array * A, int dim, ...){
    int total=1;
    va_list ap;//可视为一个char*类型的指针
    if(dim<1||dim>MAX_ARRAY_DIM){
        return ERROR;
    }
    A->dim=dim;//得到数组维数
    A->bounds=(int *)malloc(dim*sizeof(int));
    if(!A->bounds){
        return OVERFLOW;
    }
    va_start(ap,dim);
    for(int i=0;i<dim;i++){
        A->bounds[i]=va_arg(ap,int);
        if(A->bounds[i]<0){
            return ERROR;
        }
        total*=A->bounds[i];
    }
    va_end(ap);//得到记录数组维界的一串数字
    A->base=(ElemType*)malloc(total*sizeof(ElemType));
    if(!A->base){
        return OVERFLOW;
    }//根据数组元素总个数得到数组元素基址
    A->constants=(int*)malloc(dim*sizeof(int));
    if(!A->constants){
        return OVERFLOW;
    }
    A->constants[dim-1]=1;
    for(int 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 *begin){
    int index;
    *begin=0;
    for(int i=0;i<A.dim;i++){
        index=va_arg(ap,int);
        if(index<1||index>A.bounds[i]){
            return ERROR;
        }
        *begin+=A.constants[i]*index;
    }
    return OK;
}
  • 得到数组中某个地址的元素值
Status Value(Array A, ElemType *e ,...){
    va_list ap;
    int begin;
    va_start(ap,*e);
    if(!Locate(A,ap,&begin)){
        return ERROR;
    }
    va_end(ap);
    *e=*(A.base+begin);
    return OK;
}
  • 赋予数组中某个地址值
Status Assign(Array * A, ElemType e, ...){
    va_list ap;
    int begin;
    va_start(ap,e);
    if(!Locate(*A,ap,&begin)){
        return ERROR;
    }
    va_end(ap);
    *(A->base+begin)=e;
    return OK;
}
关注公众号,让我们携手共进0.5.jpg

无欲则刚
76 声望15 粉丝