数组的顺序存储表示

#include<stdio.h>
#include<stdarg.h>         //标准头文件获取变长参数表,提供宏va_start,va_arg,va_end
#include<stdlib.h>

#define MAX_ARRAY_DIM 8    //定义数组的最大维度
#define ERROR 0
#define OK 1
#define OVERFLOW -1
typedef int ElemType;
typedef int Status;

typedef struct{
    ElemType * base;     //数组元素的基址,由InitArray分配
    int dim;            //维度
    int *bounds;       //数组的维界基址,由InitArray分配,指向一个数组B(存储数组A的各维度的元素的数目)
    int *constants;   //数组映像函数常量基址,由InitArray分配,指向一个数组C, 它存放了"数组A各个维度上的数字加一时, 元素在线性结构L上所移动的距离
}Array;

//初始化数组
Status InitArray(Array *A, int dim, ...)
{
    //统计元素总数目,进而分配数组的基址
    int elemtotal = 1;
    int i;


    //判断维度是否合法
    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_list ap;

    va_start(ap, dim);

    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(-1);
    }

    //求映像函数的常数ci,即保存指针增减移动的元素的个数
    A->constants = (int *)malloc(dim * sizeof(int));
    if(!A->constants)
    {
        exit(-1);
    }

    A->constants[dim-1] = 1;      //最高维,指针每次移动一个元素单位

    for(i = dim - 2; i >= 0; --i)
    {
        //第i维的指针每次移动的距离 = i+1维元素的数目 * i+1维指针每次移动的距离
        A->constants[i] = A->bounds[i+1] * A->constants[i+1];
    }

    return OK;
}

//销毁数组
Status DestroyArray(Array *A)
{
    //判断数组的基址是否为空,free(NULL)是不允许的
    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)
{
    int i;
    int tag;
    //若各维度合法,求出该元素的相对地址
    (*off) = 0;          //相对于第一个元素的地址

    for(i = 0; i < A.dim; ++i)
    {
        tag = va_arg(ap, int);
        if(tag < 0 || tag > A.bounds[i])
        {
            return ERROR;          //维度不合法
        }
        (*off) = (*off) + tag * A.constants[i];       //注意是tag,不明白画图三维数组
    }

    return OK;
}

//取指定下标元素的值,赋值给e
Status Value(Array A, ElemType *e, ...)
{
    int result, off;
    va_list ap;
    va_start(ap, *e);
    if((result = Locate(A, ap, &off)) <= 0)
    {
        return result;
    }

    (*e) = *(A.base + off);
    return OK;
}

Status Assign(Array *A, ElemType e, ...)
{
    va_list ap;
    va_start(ap, e);
    int result, off;

    if((result = Locate(*A, ap, &off)) <= 0)
    {
        return result;
    }

    *(A->base + off) = e;
    return OK;
}


int main(void)
{
    Array A;
    int e;

    InitArray(&A, 3, 3, 3, 3);
    Assign(&A, 10, 0, 1, 2);
    Value(A, &e, 0, 1, 2);
    printf("%d", e);
    return 0;
}
posted @ 2019-07-13 20:00  telankesi  阅读(939)  评论(0编辑  收藏  举报