我知道有关动态分配/解除分配2D数组的算法,但是对于3D数组我不太确定。 利用这些知识和一点对称性,我想出了以下代码 (我在编码期间很难在3D中进行可视化)。
请评论正确性并建议任何更好的替代方案(效率方面或直观方式),如果有的话
此外,我认为这些2D和3D数组都可以正常访问,如静态数组,如arr2D [2] [3]和
arr3D [2] [3] [2]。对?
2D代码
//allocate a 2D array
int** allocate2D(int rows,int cols)
{
int **arr2D;
int i;
arr2D = (int**)malloc(rows*sizeof(int*));
for(i=0;i<rows;i++)
{
arr2D[i] = (int*)malloc(cols*sizeof(int));
}
}
//deallocate a 2D array
void deallocate2D(int** arr2D,int rows)
{
int i;
for(i=0;i<rows;i++)
{
free(arr2D[i]);
}
free(arr2D);
}
3D代码
//allocate a 3D array
int*** allocate3D(int l,int m,int n)
{
int ***arr3D;
int i,j,k;
arr3D = (int***)malloc(l * sizeof(int **));
for(i=0;i<l;i++)
{
arr3D[i] = (int**)malloc(m * sizeof(int*));
for(j=0;j<m;j++)
{
arr3D[i][j] = (int*)malloc(n*sizeof(int));
}
}
return arr3D;
}
//deallocate a 3D array
void deallocate3D(int arr3D,int l,int m)
{
int i,j;
for(i=0;i<l;i++)
{
for(int j=0;j<m;j++)
{
free(arr3D[i][j]);
}
free(arr3D[i]);
}
free(arr3D);
}
答案 0 :(得分:11)
您还可以分配一个数组并计算单个索引。这需要更少的分配器调用,并导致更少的碎片和更好的缓存使用。
typedef struct {
int a;
int b;
int* data;
} Int2d;
Int2d arr2d = { 2, 3 };
arr2d.data = malloc(arr2d.a * arr2d.b * sizeof *arr2d.data);
现在arr2d[r][c]
变为arr2d.data[r * arr2d.b + c]
。解除分配是一个免费的()。作为奖励,您一定要随身携带动态阵列尺寸。
外推到3d:
typedef struct {
int a;
int b;
int c;
int* data;
} Int3d;
Int3d arr3d = { 2, 3, 4 };
arr3d.data = malloc(arr3d.a * arr3d.b * arr3d.c * sizeof *arr3d.data);
//arr3d[r][c][d]
// becomes:
arr3d.data[r * (arr3d.b * arr3d.c) + c * arr3d.c + d];
您应该在单独的函数或宏中封装这些索引操作(以及(de)分配)。
(r,c和d的名称可能更好 - 我的目的是行,列和深度。虽然a,b和c是相应尺寸的限制,你可能更喜欢像n1这样的东西, n2,n3那里,甚至为他们使用数组。)
答案 1 :(得分:4)
arr3d应该是一个三指针而不仅仅是一个int。否则看起来没问题:
void deallocate3D(int*** arr3D,int l,int m)
{
int i,j;
for(i=0;i<l;i++)
{
for(int j=0;j<m;j++)
{
free(arr3D[i][j]);
}
free(arr3D[i]);
}
free(arr3D);
}
arr3D是一个指向指针的指针,因此arr3D [i]是一个指向指针的指针而arr3D [i] [j]只是一个指针。首先在循环中释放最小尺寸是正确的,然后爬上尺寸直到arr3D本身被释放。
同样,隐含地赋予malloc
指向类型的sizeof更为惯用。而不是:
arr3D[i] = (int**)malloc(m * sizeof(int*));
成功:
arr3D[i] = (int**)malloc(m * sizeof(*arr3D[i]));
是的,这种动态分配的多维数组可以像静态分配的多维数组一样被访问。
答案 2 :(得分:1)
您可以看到以下代码:
#include <stdio.h>
#include <stdlib.h>
void main()
{
// Array 3 Dimensions
int x = 4, y = 5, z = 6;
// Array Iterators
int i, j, k;
// Allocate 3D Array
int *allElements = malloc(x * y * z * sizeof(int));
int ***array3D = malloc(x * sizeof(int **));
for(i = 0; i < x; i++)
{
array3D[i] = malloc(y * sizeof(int *));
for(j = 0; j < y; j++)
{
array3D[i][j] = allElements + (i * y * z) + (j * z);
}
}
// Access array elements
for(i = 0; i < x; i++)
{
printf("%d\n", i);
for(j = 0; j < y; j++)
{
printf("\n");
for(k = 0; k < z; k++)
{
array3D[i][j][k] = (i * y * z) + (j * z) + k;
printf("\t%d", array3D[i][j][k]);
}
}
printf("\n\n");
}
// Deallocate 3D array
free(allElements);
for(i = 0; i < x; i++)
{
free(array3D[i]);
}
free (array3D);
}
有关详细信息,请参阅此链接3d array
答案 3 :(得分:0)
这是该问题的一个版本,但只使用了一个malloc,受到其他答案的启发。它允许直观地使用方括号并易于清洁。我希望它不会使任何编译器实现特定的假设。
int main(int argc, char *argv[])
{
int **array, i, j;
array = allocate2d(3, 4);
for (i = 0; i < 3; i++)
{
for (j = 0; j < 4; j++)
{
array[i][j] = j + i + 1;
}
}
for (i = 0; i < 3; i++)
{
for (j = 0; j < 4; j++)
{
printf("array[%d][%d] = %d\n", i, j, array[i][j]);
}
}
free(array);
return EXIT_SUCCESS;
}
int **allocate2d(int x, int y)
{
int i;
int **array = malloc(sizeof(int *) * x + sizeof(int) * x * y);
for (i = 0; i < x; i++)
{
array[i] = ((int *)(array + x)) + y * i;
}
return array;
}