一维线性表如何构建多维数组

173 阅读3分钟

理论整理

下面是一维、二维、三维的现实状态,人类的想象力有限,高于思维的很难找到现实,但是对于计算机来说,可以表示任意维度的数组
在这里插入图片描述

一维

长度为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…