10

Conozco los algoritmos para asignar/desasignar una matriz bidimensional de forma dinámica, sin embargo, no estoy muy seguro de lo mismo para las matrices 3D.
Usando este conocimiento y un poco de simetría, se me ocurrió el siguiente código.
(tuve dificultades para visualizar en 3D durante la codificación).asignación/desasignación dinámica de matrices en 2D y 3D

Comente sobre la corrección y sugiera una mejor alternativa (eficiente o intuitiva), en su caso.
Además, creo que a estas matrices 2D y 3D se puede acceder normalmente como matrices estáticas como arr2D [2] [3] y
arr3D [2] [3] [2]. ¿Derecha?

Código de 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); 
} 

Código de 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); 
} 

Respuesta

11

También puede asignar una matriz y calcular índices individuales. Esto requiere menos llamadas de asignador y resultados en una menor fragmentación y un mejor uso de la memoria caché.

typedef struct { 
    int a; 
    int b; 
    int* data; 
} Int2d; 

Int2d arr2d = { 2, 3 }; 
arr2d.data = malloc(arr2d.a * arr2d.b * sizeof *arr2d.data); 

Ahora arr2d[r][c] convierte arr2d.data[r * arr2d.b + c]. La desasignación es un solo free() de distancia. Como beneficio adicional, asegúrese de mantener siempre sus tamaños de matriz dinámicos con usted.

Extrapolando a 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]; 

Usted debe encapsular estas operaciones de índice (y las (des) las asignaciones para el caso) en una función o macro por separado.

(Los nombres de r, c y d podrían ser mejores — Iba por la fila, la columna y la profundidad. Mientras que a, byc son los límites de sus dimensiones correspondientes, es posible que prefiera algo como n1 , n2, n3 allí, o incluso usar una matriz para ellos.)

+0

también puede asignar una matriz n dimensional en un solo bloque lo suficientemente grande como para contener punteros y datos. De esa manera puede ir int ***** array = allocate (sizeof (int), 10, 10, 10, 10, 10, 0); para asignar una matriz int 5D e indexarla mediante la matriz [a] [b] [c] [d] [e] sin la necesidad de calcular los índices. Utilicé esto cuando tuve que reemplazar grandes matrices de pila con montones para programar para trabajar en teléfonos con un tamaño de pila limitado sin necesidad de hacer ajustes serios al código que indexa las matrices. Vea aquí: https://sourceforge.net/p/gnugos60/code/HEAD/tree/trunk/GNUGoS60/common/src/ndMalloc.cpp – idij

4

arr3d debe ser un puntero triples y no sólo un int. De lo contrario se ve bien:

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 es un puntero a puntero a puntero, por lo arr3D [i] es un puntero-a-puntero y arr3D [i] [j] simplemente un puntero. Es correcto liberar primero la dimensión más baja de un ciclo, y luego subir las dimensiones hasta que se libere el propio arr3D.

También es más idiomático dar malloc el tamaño del tipo de punta implícitamente. En lugar de:

arr3D[i] = (int**)malloc(m * sizeof(int*)); 

Que sea:

arr3D[i] = (int**)malloc(m * sizeof(*arr3D[i])); 

Y sí, este tipo de matrices multidimensionales asignados dinámicamente se puede acceder matrices multidimensionales tan estáticamente asignados.

+0

+1 por buenos consejos. – Ankur

1

Se puede ver el código de abajo:

#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); 
} 

Para más detalles, véase este enlace 3d array

0

Ésta es una versión de la idea en la pregunta, pero utilizando sólo un malloc, inspirado por el otro respuestas Permite el uso intuitivo de los corchetes y una fácil limpieza. Espero que no haga ninguna suposición específica de implementación del compilador.

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; 
} 
Cuestiones relacionadas