Wielowymiarowe Tablice C++ na stercie

Jak mógłbym dynamicznie przydzielać wielowymiarową tablicę?

Author: Garrett, 2008-12-04

12 answers

Jeśli znasz już Rozmiar zagnieżdżonych wymiarów, możesz również dosłownie przydzielić tablicę wielowymiarową używając new:

typedef int dimensions[3][4];

dimensions * dim = new dimensions[10];
dim[/* from 0 to 9 */][/* from 0 to 2 */][/* from 0 to 3 */] = 42;
delete [] dim;

Zamiast 10 może zostać przekazana określona wartość runtime. Ponieważ nie jest częścią operatora type new returns, jest to dozwolone. Jest to miłe, jeśli znasz liczbę kolumn, ale chcesz zachować zmienną liczbę wierszy, na przykład. Typedef ułatwia odczyt kodu.

 24
Author: Johannes Schaub - litb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-04 15:30:38

Ze względu na kompletność, tutaj jest lepszy sposób, aby to zrobić w C++, gdy znasz granice tablic z wyprzedzeniem. Zaletą korzystania z poniższej klasy jest to, że nie musisz przejmować się wywołaniem delete[] na swoich danych. Oznacza to, że ta klasa będzie bezpieczna dla wyjątków i wszystkich innych wspaniałych rzeczy o RAII .

template<typename T, int width, int height>
class MultiArray
{
    private:
        typedef T cols[height];
        cols * data;
    public:
        T& operator() (int x, int y) { return data[x][y]; }
        MultiArray() { data = new cols[width]; }
        ~MultiArray() { delete [] data; }
};

Użycie:

MultiArray<int, 10, 10> myArray;
myArray(2, 3) = 4;
cout << myArray(2, 3);

edit: i, skoro już jestem przy tym, oto konfiguracja, której możesz użyć, jeśli nie znasz granice tablicy until runtime:

template<typename T>
class Array2D
{
    private:
        const int width;
        T * data;
    public:
        T& operator() (int x, int y) { return data[y*width + x]; }
        Array2D(const int w, const int h) : width(w) { data = new T[w*h]; }
        ~Array2D() { delete [] data; }
};

Użycie:

Array2D myArray(10, 10);
myArray(3, 4) = 42;
cout << myArray(3, 4);
 6
Author: e.James,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-04 16:40:43

Jak o użyciu Boost.Multiarray ? Wierzę, że to odpowiada na twoje potrzeby całkiem dobrze ! http://www.boost.org/doc/libs/1_37_0/libs/multi_array/doc/user.html#sec_introduction

Oto fragment strony dokumentacji:

 #include < boost/multi_array.hpp >

 #include < cassert >

int main () 

{

  // Create a 3D array that is 3 x 4 x 2

  typedef boost::multi_array< double, 3 > array_type;

  typedef array_type::index index;

  array_type A(boost::extents[3][4][2]);


  // Assign values to the elements

  int values = 0;

  for(index i = 0; i != 3; ++i) 

    for(index j = 0; j != 4; ++j)

      for(index k = 0; k != 2; ++k)

        A[i][j][k] = values++;

  // Verify values

  int verify = 0;

  for(index i = 0; i != 3; ++i) 

    for(index j = 0; j != 4; ++j)

      for(index k = 0; k != 2; ++k)

        assert(A[i][j][k] == verify++);

  return 0;

}
 6
Author: Benoît,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-06 01:05:03

Zobacz to: C++ FAQ by Marshall Cline

Zobacz " jak przydzielić tablice wielowymiarowe przy użyciu new?"I" ale poprzedni kod FAQ jest tak trudne i podatne na błędy! Nie ma prostszego sposobu?"sekcje.

 6
Author: Naveen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-23 09:02:04

std::vector<std::vector<int> >należy wspomnieć, ponieważ często jest to najprostszy sposób. Należy jednak pamiętać, że nie jest prostokątna. Nie każda std::vector<int> musi mieć taką samą długość.

 3
Author: MSalters,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-04 15:52:27

Dziwi mnie, że nikt jeszcze nie wspomniał o boost::multi_array. W zeszłym tygodniu potrzebowałem tablicy 2D w programie i okazało się, że jest ona o wiele łatwiejsza i szybsza w kodowaniu niż domowe rozwiązania, które wymyśliłem wcześniej (o których wszystkie są wymienione w innych komentarzach).

 3
Author: Head Geek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-04 17:53:29

Oto implementacja, którą mam; deklaruję pojedynczy przylegający blok ints zamiast tworzyć nowe bloki wewnątrz mojej pętli for, więc nie powoduję błędów strony w całym miejscu. Podziękowania dla ejamesa za wskazanie, dlaczego ten kod został pierwotnie złamany.

int width = 10, height = 10, totalSize = width*height;
int **myArray = new int*[width];
int *data = new int[totalSize];

for ( int i = 0; i < height; ++i )
{
    myArray[i] = data + (i*width);
}

// do some things here

delete[] data;
delete[] myArray;
 3
Author: eplawless,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-05 07:05:20

Pętla nie zapisuje wartości wskaźnika do myArray poprawnie. Sugerowałbym zamiast tego:

int width = 10;
int height = 10;
int ** myArray = new int*[width];
int * data = new int[width*height];
int * index = data;
for (int i = 0; i < width; i++)
{
    myArray[i] = index;
    index += height;
}

// ...

delete[] data;
delete[] myArray;
 2
Author: e.James,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-04 16:26:24

Jako alternatywa, STLSoft zawiera klasę fixed_array_2d (jak również wersje 3D i 4D). W porównaniu z podanymi tutaj rozwiązaniami homebrewed, ma podobną implementację, ale bardziej kompletny zestaw funkcji (pełne wsparcie dla iteratorów itp.). W porównaniu z boost:: multi_array, jest lżejszy i łatwiejszy w niezbyt zgodnych kompilatorach C++, ale (celowo) brakuje niektórych funkcji multi_array.

 2
Author: Josh Kelley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-06 02:21:52

Możesz zindeksować jednowymiarowy jako 2, 3 lub N wymiarowy, jeśli tylko odstępujesz od odpowiedniej ilości elementów. Na przykład, jeśli mam 10 wierszy i 10 kolumn, wiem, że jeśli jestem w wierszu 3 będę musiał przejść przez co najmniej 30 elementów, aby się do niego dostać.

Jakoś wolę tę notację dla prostych tablic 2D, ponieważ nie muszę się martwić zagnieżdżonymi poziomami wskaźników. Minusem jest notacja Messiera. Oto przykład z tablicą 2D z N rzędami I m Kolumny:

int *matrix = new int[n*m];

//set element (3,7) to 10
matrix[3*m+7] = 10;

//print the matrix
for (int i = 0; i < n; i++) {
  for (int j = 0; j < m; j++) {
    cout << matrix[i*m+j] << ' ';
  }
  cout << '\n';
}
 0
Author: Rich,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-04 17:20:41

Moje pytanie tutaj obejmuje głównie ten sam temat dość dobrze dzięki kilku znakomitym odpowiedziom. Nie obejmuje jednak tablic N-wymiarowych, których nie widziałem w odpowiedziach tutaj, ale byłoby to przydatne.

 0
Author: Tristan Havelick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:14:13

To reprodukcja posta w innym wątku. Robi dokładnie to, co chcesz, bez konieczności znajomości wymiarów tablicy z wyprzedzeniem i bez użycia boost lub STL.

Oto procedura, która przydziela tablicę 3D o wymiarach N1 x N2 x N3 w ciągłej przestrzeni pamięci, jednocześnie pozwalając na składnię A [I] [j] [k] dla dostępu operatora. Tablica jest dynamiczna, ale ciągła, więc jest to ogromny plus nad podejściem wektorowym i pętlami nowych wywołań [].

template <class T> T ***Create3D(int N1, int N2, int N3)
{
    T *** array = new T ** [N1];

    array[0] = new T * [N1*N2];

    array[0][0] = new T [N1*N2*N3];

    int i,j,k;

    for( i = 0; i < N1; i++) {

        if (i < N1 -1 ) {

            array[0][(i+1)*N2] = &(array[0][0][(i+1)*N3*N2]);

            array[i+1] = &(array[0][(i+1)*N2]);

        }

        for( j = 0; j < N2; j++) {     
            if (j > 0) array[i][j] = array[i][j-1] + N3;
        }

    }

    cout << endl;
    return array;
};

template <class T> void Delete3D(T ***array) {
    delete[] array[0][0]; 
    delete[] array[0];
    delete[] array;
};

I później w Twoim procedury wdrażania...

int *** array3d;
int N1=4, N2=3, N3=2;

int elementNumber = 0;

array3d = Create3D<int>(N1,N2,N3);

//equivalently, a 'flat' array could be obtained with
//int * array = array3d[0][0];

cout << "{" << endl;
for (i=0; i<N1; i++) {
    cout << "{";
    for (j=0; j<N2; j++) {
        cout << "{";
        for (k=0; k<N3; k++) {
            array3d[i][j][k] = elementNumber++;
            cout << setw(4) << array3d[i][j][k] << " ";

            //or if you're using the flat array:
            //array[i*N2*N3 + j*N3 + k] = elementNumber++;

        }
        cout << "}";
    }
    cout << "}";
    cout << endl ;
}
cout << "}" << endl;

Delete3D(array3d);

Daje wyjście:

{
{{   0    1 }{   2    3 }{   4    5 }}
{{   6    7 }{   8    9 }{  10   11 }}
{{  12   13 }{  14   15 }{  16   17 }}
{{  18   19 }{  20   21 }{  22   23 }}
}
 0
Author: v.chaplin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-05 14:31:47