理论整理
下面是一维、二维、三维的现实状态,人类的想象力有限,高于思维的很难找到现实,但是对于计算机来说,可以表示任意维度的数组
一维
长度为12的一维数据
二维
第一维是长度为4(括号①内有多少元素),第二维是长度为3(括号②有多少个①括号),对应图中的3行4列的二维数组
三维
第一维是长度为4(括号①内有多少元素),第二维是长度为3(括号②有多少个①括号),第三维是长度为2(括号③有多少个②括号),对应图中的3行4列2层的三维数组
N维
如上,我们不停的迭代即可,通过上述过程,我们可以知道一维数组可以表示任意维度的数组
实现(c语言版本)
定义类型
typedef int ElemType;
typedef struct
{
// 数组元素基址
ElemType * base;
int dim;
int * bounds;
int * constants;
}Array;
如何理解这四个参数,举例说明
- base为存储空间的起始地址
- dim表示维度
- bounds存储每个维度的长度
- constants单个维度内元素间隔距离
距离说明二维情况
核心代码实现
array.h
#include "base.h"
#ifndef _ARRAY_H_
#define _ARRAY_H_
typedef int ElemType;
#define MAX_ARRAY_DIM 8
typedef struct
{
// 数组元素基址,由InitArray分配
ElemType * base;
int dim;
// 数组维界基址,由InitArray分配,存储各维的长度的数组
int * bounds;
// 数组映像函数常量基址,其实就是ci,确切说的是几个存储单元。
int * constants;
}Array;
// 若维数dim和随后的各维长度合法,则构造相应的数组A,并返回OK
Status InitArray(Array &A, int dim, ...);
// 销毁数组A
Status DestroyArray(Array &A);
// A是n维数组,e为元素变量,随后是n个下标值。
// 若各下标不超界,则e赋值为所指定的A的元素值,并返回OK
Status Value(ElemType &e, Array A, ...);
// A是n维数组,e为元素变量,随后是n个下标值。
// 若下标不超界,则将e的值赋给所指定的A的元素,并返回OK
Status Assign(Array &A, ElemType e, ...);
#endif
array.cpp
#include "array.h"
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
// 若维数dim和随后的各维长度合法,则构造相应的数组A,并返回OK
Status InitArray(Array &A, int dim, ...)
{
if (dim < 1 || dim > MAX_ARRAY_DIM)
{
return ERROR;
}
A.dim = dim;
A.bounds = (int *) malloc(dim * sizeof(int));
if (!A.bounds)
{
exit(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)
{
exit(OVERFLOW);
}
elemtotal *= A.bounds[i];
}
va_end(ap);
// 分配内存
A.base = (ElemType *) malloc(dim * sizeof(ElemType));
if (!A.base)
{
exit(OVERFLOW);
}
// 数组映像函数常量基址,其实就是ci,确切说的是几个存储单元
A.constants = (int *) malloc(dim * sizeof(int));
if (!A.constants)
{
exit(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;
}
// 销毁数组A
Status DestroyArray(Array &A)
{
if (!A.base)
{
free(A.base);
A.base = NULL;
}
if (!A.bounds)
{
free(A.bounds);
A.bounds = NULL;
}
if (!A.constants)
{
free(A.constants);
A.constants = NULL;
}
return OK;
}
// 若ap指示的各下标值合法,则求出该元素在A中的相对地址off
Status Locate(Array A, va_list ap, int &off)
{
off = 0;
for (int i = 0; i < A.dim; i++)
{
int ind = va_arg(ap, int);
if (ind < 0 || ind > A.bounds[i])
{
return ERROR;
}
off += A.constants[i] * ind;
}
return OK;
}
// A是n维数组,e为元素变量,随后是n个下标值。
// 若各下标不超界,则e赋值为所指定的A的元素值,并返回OK
Status Value(ElemType &e, Array A, ...)
{
va_list ap;
va_start(ap, A);
int offset = 0;
if (Locate(A, ap, offset) != OK)
{
return ERROR;
}
e = * (A.base + offset);
va_end(ap);
return OK;
}
// A是n维数组,e为元素变量,随后是n个下标值。
// 若下标不超界,则将e的值赋给所指定的A的元素,并返回OK
Status Assign(Array &A, ElemType e, ...)
{
va_list temp;
va_start(temp, e);
int offset = 0;
if (Locate(A, temp, offset) != OK)
{
return ERROR;
}
* (A.base + offset) = e;
va_end(temp);
return OK;
}
测试类
#include <stdio.h>
#include "array.h"
// 四维演示
int main()
{
Array A;
// int a[3][2][2];
InitArray(A, 4, 3, 2, 2, 1);
int value = 1;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 2; j++)
{
for (int k = 0; k < 2; k++)
{
for (int m = 0; m < 1; m++)
{
printf("(x, y, z, m) = (%d, %d, %d, %d) = %d\n", i, j, k, m, value);
Assign(A, value++, i, j, k, m);
}
}
}
}
int * p = A.base;
for (int i = 0; i < 12; i++)
{
printf("%d ", * (p + i));
}
printf("\n");
ElemType e = 1;
Value(e, A, 1, 1, 1, 0);
printf("(1, 1, 1, 0) = %d\n", e);
return 0;
}
完成代码地址:github.com/dengjili/da…