数据结构之多维数组
定义结构体
typedef struct {
ElemType* base;
int dim;
int* bounds;
int* constants;
}Array;
各基本操作函数原型说明
Status InitArray(Array* A, int dim, ...);
Status DestroyArray(Array* A);
Status LocateArray(Array A, va_list ap, int* offset);
Status SetArray(Array* A, ElemType e, ...);
Status GetValue(ElemType* e, Array A, ...);
各基本操作的具体实现
(1)创建数组函数实现
Status InitArray(Array* A, int dim, ...) {
if (dim <1 || dim>MAX_ARRAY_DIM) return ERROR;
A->dim = dim;
A->bounds = (int*)malloc(sizeof(int) * dim);
if (!A->bounds) return OVERFLOW;
int elemtotal = 1;
va_list ap;
va_start(ap, dim);
for (int i = 0; i < dim; ++i) {
A->bounds[i] = va_arg(ap, int);
if (A->bounds[i] < 0)return UNDERFLOW;
elemtotal *= A->bounds[i];
}
va_end(ap);
A->base = (ElemType*)malloc(sizeof(ElemType) * elemtotal);
if (!A->base) return OVERFLOW;
A->constants = (int*)malloc(sizeof(int) * dim);
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;
}
(2)销毁数组函数实现
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;
}
(3)数组定位函数实现
Status LocateArray(Array A, va_list ap, int* offset) {
int i, instand;
*offset = 0;
for (i = 0; i < A.dim; i++) {
instand = va_arg(ap, int);
if (instand < 0 || instand > A.bounds[i]) {
return ERROR;
}
*offset += A.constants[i] * instand;
}
return OK;
}
(4)数组元素赋值函数实现
Status SetArray(Array *A, ElemType e, ...) {
va_list ap;
int offset;
va_start(ap, e);
if (LocateArray(*A, ap, &offset) == ERROR) return ERROR;
va_end(ap);
*(A->base + offset) = e;
return OK;
}
(5)取出数组元素函数实现
Status GetValue(ElemType* e, Array A, ...) {
va_list ap;
int offset;
va_start(ap, A);
if (LocateArray(A, ap, &offset) == ERROR) return ERROR;
va_end(ap);
*e = *(A.base + offset);
return OK;
}
测试分析
-
创建 创建一个二维数组,其第一维长度为4,第二维长度为3。 测试代码: 运行结果: -
销毁 将结构体A的地址传入到DestroyArray函数中,执行操作。 测试代码: 运行结果: -
数组元素赋值 定义二维数组B[4][3],通过SetArray函数将其值赋给数组A,通过遍历输出A中元素的值,则可以判断出赋值是否准确。 测试代码: 运行结果: -
取出数组元素 测试代码: 运行结果:
思考与小结
1、 对数组的再认识
存储器的结构是一维线性的结构,数组是多维的结构。如果要将一个多维的结构放在一个一维的存储单元里,就必须先将多维的数组转换成一个一维的线性序列,才能将其放在存储器当中。数组的存储方式主要有两种:一张是以行序为主的存储方式,另外一种是以列序为主的存储方式。
2、调试过程中遇到的问题及解决方案
1、两次编译报错 ①错误信息:va_start argument must not have reference type and must not be parenthesized; va_start函数的运用问题,函数原型:void va_start(va_list ap,parmN);报错原因为参数不正确。查看c语言开发手册,得出原因。 ap 一个va_list类型的实例 Prmhn 第一个变量参数前的命名参数 ②错误信息:*LNK2019 无法解析的外部符号 "int __cdecl SetArray(struct Array ,int,int,…)" (?SetArray@@YAHPAUArray@@HHZZ),函数 _main 中引用了该符号 此错误信息为,找的到定义却又未找到实现的函数,故需将函数实现后才能调用,同时注意参数的对应,避免出现以上问题。 2、运行时报错 运行时报错,数据访问出现问题。通过检查报错信息的前后语句,发现在访问数组的时候忘记i+1,导致i走到-1形成错误原因。 3、运行结果出错 运行结果出现了地址与数值都输出的情况,通过调试,发现第一次进入LocateArray函数之后,函数返回了ERROR,通过打印语句检查,函数确实进入了判断语句内,返回ERROR; 表明参数不准确或者函数判断语句不正确,由于数值为自己控制的,故参数不准确的可能性较小,仔细分析了参数临界以及函数逻辑,将判断参数的条件改成正确判断语句。得到正确的结果。
3、算法的时间复杂度分析
InitArray函数的时间复杂度为O(n); DestroyArray函数的时间复杂度为O(1); LocateArray函数的时间复杂度为O(n); SetArray函数的时间复杂度为O(n); GetArray函数的时间复杂度为O(n); SetArray函数和GetArray函数的时间复杂度主要受LocateArray函数影响。
|