2009-12-01 118 views
10

我知道動態分配/取消分配二維數組的算法,但我對三維數組的相同性不太確定。
利用這些知識和一些對稱性,我想出了下面的代碼。
(在編碼過程中,我很難在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); 
} 

回答

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

你應該在一個單獨的函數或宏封裝這些索引操作(和(去)分配爲此事)。

(r,c和d的名字可能更好—我正在考慮行,列和深度,而a,b和c是它們對應維度的限制,你可能更喜歡n1 ,n2,n3,甚至爲他們使用數組。)

+0

您還可以在一個足夠大的單個塊中分配一個n維數組,以包含指針和數據。這樣你可以去int ***** array = allocate(sizeof(int),10,10,10,10,10,0);分配一個5D int數組,並通過數組[a] [b] [c] [d] [e]將其索引,而不需要計算索引。當我需要用堆堆棧來替換大堆棧數組時,我使用了這個代碼,以便在堆棧大小有限的手機上工作,而無需對代碼索引數組進行嚴格調整。看到這裏:https://sourceforge.net/p/gnugos60/code/HEAD/tree/trunk/GNUGoS60/common/src/ndMalloc.cpp – idij 2016-08-03 10:49:02

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])); 

是的,這種動態分配的多維數組可以被訪問,就像靜態分配的多維數組。

+0

+1爲好的提示。 – Ankur 2009-12-01 07:38:55

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

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