Frage

Wie ordnen Sie dynamisch eine 2D-Matrix in C ++? Ich habe versucht, auf das, was ich schon weiß:

#include <iostream>

int main(){
    int rows;
    int cols;
    int * arr;
    arr = new int[rows][cols];
 }

Es funktioniert für einen Parameter, aber jetzt für zwei Personen. Was soll ich tun?

War es hilfreich?

Lösung

Eine Matrix ist tatsächlich ein Array von Arrays.

int rows = ..., cols = ...;
int** matrix = new int*[rows];
for (int i = 0; i < rows; ++i)
    matrix[i] = new int[cols];

Natürlich die Matrix zu löschen, sollten Sie Folgendes tun:

for (int i = 0; i < rows; ++i)
    delete [] matrix[i];
delete [] matrix;

Ich habe gerade eine andere Möglichkeit herausgefunden:

int rows = ..., cols = ...;
int** matrix = new int*[rows];
if (rows)
{
    matrix[0] = new int[rows * cols];
    for (int i = 1; i < rows; ++i)
        matrix[i] = matrix[0] + i * cols;
}

Dieses Array Befreit ist einfacher:

if (rows) delete [] matrix[0];
delete [] matrix;

Diese Lösung hat den Vorteil, einen einzigen großen Speicherblock Zuweisung für alle Elemente, anstelle von mehreren kleinen Brocken. Die erste Lösung, die ich geschrieben ist ein besseres Beispiel für die Arrays von Arrays Konzept, though.

Andere Tipps

Sie können auch std::vectors um dies zu erreichen verwenden:

mit std::vector< std::vector<int> >

Beispiel:

std::vector< std::vector<int> > a;

  //m * n is the size of the matrix

    int m = 2, n = 4;
    //Grow rows by m
    a.resize(m);
    for(int i = 0 ; i < m ; ++i)
    {
        //Grow Columns by n
        a[i].resize(n);
    }
    //Now you have matrix m*n with default values

    //you can use the Matrix, now
    a[1][0]=1;
    a[1][1]=2;
    a[1][2]=3;
    a[1][3]=4;

//OR
for(i = 0 ; i < m ; ++i)
{
    for(int j = 0 ; j < n ; ++j)
    {      //modify matrix
        int x = a[i][j];
    }

}

boost :: multi_array

#include <boost/multi_array.hpp>

int main(){
    int rows;
    int cols;
    boost::multi_array<int, 2> arr(boost::extents[rows][cols] ;
}
 #include <iostream>

    int main(){
        int rows=4;
        int cols=4;
        int **arr;

        arr = new int*[rows];
        for(int i=0;i<rows;i++){
           arr[i]=new int[cols];
        }
        // statements

        for(int i=0;i<rows;i++){
           delete []arr[i];
        }
        delete []arr;
        return 0;
     }
arr = new int[cols*rows];

Wenn Sie entweder keine Syntax dagegen

arr[row * cols + col] = Aij;

oder Verwendung operator [] overaloading irgendwo. Dies kann mehr Cache-freundlich sein, als Array von Arrays, oder kann nicht sein, mehr wahrscheinlich sollte man darüber nicht. Ich will nur darauf hinweisen, dass a) Array von Arrays nicht einzige Lösung ist, b) einige Vorgänge sind einfacher zu implementieren, wenn Matrix in einem Speicherblock angeordnet. Z.

for(int i=0;i < rows*cols;++i)
   matrix[i]=someOtherMatrix[i];

eine Zeile kürzer als

for(int r=0;i < rows;++r)
  for(int c=0;i < cols;++s)
     matrix[r][c]=someOtherMatrix[r][c];

obwohl Hinzufügen von Zeilen auf eine solche Matrix ist schmerzhafter

oder Sie können nur ein 1D-Array aber Referenzelemente in einer 2D-Mode zuordnen:

Adresse Zeile 2, Spalte 3 (obere linke Ecke ist Reihe 0, Spalte 0):

arr [2 * MATRIX_WIDTH + 3]

wobei MATRIX_WIDTH ist die Anzahl von Elementen in einer Reihe.

Die andere Antwort beschreibt Arrays von Arrays korrekt sind.
Aber wenn Sie planen, eine etwas mathematische mit der Arrays zu tun - oder etwas brauchen besondere wie dünn besetzte Matrizen sollten Sie bei einem der vielen Mathematik-Libs aussehen TNT , bevor neu zu erfinden zu viele Räder

Ich habe diese Raster-Klasse, die als einfache Matrix verwendet werden kann, wenn Sie keine mathematischen Operatoren müssen.

/**
 * Represents a grid of values.
 * Indices are zero-based.
 */
template<class T>
class GenericGrid
{
    public:
        GenericGrid(size_t numRows, size_t numColumns);

        GenericGrid(size_t numRows, size_t numColumns, const T & inInitialValue);

        const T & get(size_t row, size_t col) const;

        T & get(size_t row, size_t col);

        void set(size_t row, size_t col, const T & inT);

        size_t numRows() const;

        size_t numColumns() const;

    private:
        size_t mNumRows;
        size_t mNumColumns;
        std::vector<T> mData;
};


template<class T>
GenericGrid<T>::GenericGrid(size_t numRows, size_t numColumns):
    mNumRows(numRows),
    mNumColumns(numColumns)
{
    mData.resize(numRows*numColumns);
}


template<class T>
GenericGrid<T>::GenericGrid(size_t numRows, size_t numColumns, const T & inInitialValue):
    mNumRows(numRows),
    mNumColumns(numColumns)
{
    mData.resize(numRows*numColumns, inInitialValue);
}


template<class T>
const T & GenericGrid<T>::get(size_t rowIdx, size_t colIdx) const
{
    return mData[rowIdx*mNumColumns + colIdx];
}


template<class T>
T & GenericGrid<T>::get(size_t rowIdx, size_t colIdx)
{
    return mData[rowIdx*mNumColumns + colIdx];
}


template<class T>
void GenericGrid<T>::set(size_t rowIdx, size_t colIdx, const T & inT)
{
    mData[rowIdx*mNumColumns + colIdx] = inT;
}


template<class T>
size_t GenericGrid<T>::numRows() const
{
    return mNumRows;
}


template<class T>
size_t GenericGrid<T>::numColumns() const
{
    return mNumColumns;
}

das Doppelzeiger Verwendung ist bei weitem der beste Kompromiss zwischen Ausführungsgeschwindigkeit / Optimierung und Lesbarkeit. ein einzelnes Array mit Inhalt zu speichern Matrix‘ist, was eigentlich ein Doppelzeiger der Fall ist.

Ich habe erfolgreich die folgenden Templat-Schöpfer Funktion (ja, ich weiß, dass ich alte C-Stil Zeiger Referenzierung verwenden, aber es tut Code deutlicher auf der rufenden Seite in Bezug auf das Ändern von Parametern machen - etwas, was ich über Zeiger wie das ist, nicht möglich, mit Referenzen Sie werden sehen, was ich meine).

///
/// Matrix Allocator Utility
/// @param pppArray Pointer to the double-pointer where the matrix should be allocated.
/// @param iRows Number of rows.
/// @param iColumns Number of columns.
/// @return Successful allocation returns true, else false.
template <typename T>
bool NewMatrix(T*** pppArray, 
               size_t iRows, 
               size_t iColumns)
{
   bool l_bResult = false;
   if (pppArray != 0) // Test if pointer holds a valid address.
   {                  // I prefer using the shorter 0 in stead of NULL.
      if (!((*pppArray) != 0)) // Test if the first element is currently unassigned.
      {                        // The "double-not" evaluates a little quicker in general.
         // Allocate and assign pointer array.
         (*pppArray) = new T* [iRows]; 
         if ((*pppArray) != 0) // Test if pointer-array allocation was successful.
         {
            // Allocate and assign common data storage array.
            (*pppArray)[0] = new T [iRows * iColumns]; 
            if ((*pppArray)[0] != 0) // Test if data array allocation was successful.
            {
               // Using pointer arithmetic requires the least overhead. There is no 
               // expensive repeated multiplication involved and very little additional 
               // memory is used for temporary variables.
               T** l_ppRow = (*pppArray);
               T* l_pRowFirstElement = l_ppRow[0];
               for (size_t l_iRow = 1; l_iRow < iRows; l_iRow++)
               {
                  l_ppRow++;
                  l_pRowFirstElement += iColumns;
                  l_ppRow[0] = l_pRowFirstElement;
               }
               l_bResult = true;
            }
         }
      }
   }
}

Um den Speicher de-allocate die oben angegebene Dienstprogramm erstellt, hat man einfach de-Zuweisung in umgekehrter Richtung.

///
/// Matrix De-Allocator Utility
/// @param pppArray Pointer to the double-pointer where the matrix should be de-allocated.
/// @return Successful de-allocation returns true, else false.
template <typename T>
bool DeleteMatrix(T*** pppArray)
{
   bool l_bResult = false;
   if (pppArray != 0) // Test if pointer holds a valid address.
   {
      if ((*pppArray) != 0) // Test if pointer array was assigned.
      {
         if ((*pppArray)[0] != 0) // Test if data array was assigned.
         {
               // De-allocate common storage array.
               delete [] (*pppArray)[0];
            }
         }
         // De-allocate pointer array.
         delete [] (*pppArray);
         (*pppArray) = 0;
         l_bResult = true;
      }
   }
}

Um diese oben genannten Template-Funktionen zu verwenden, ist dann sehr einfach (z.):

   .
   .
   .
   double l_ppMatrix = 0;
   NewMatrix(&l_ppMatrix, 3, 3); // Create a 3 x 3 Matrix and store it in l_ppMatrix.
   .
   .
   .
   DeleteMatrix(&l_ppMatrix);
const int nRows = 20;
const int nCols = 10;
int (*name)[nCols] = new int[nRows][nCols];
std::memset(name, 0, sizeof(int) * nRows * nCols); //row major contiguous memory
name[0][0] = 1; //first element
name[nRows-1][nCols-1] = 1; //last element
delete[] name;

Hier ist die klare und intuitive Weise, die ich kenne einen dynamischen 2D-Array in C ++ zu vergeben. Templated in diesem Beispiel erstreckt sich auf alle Fälle.

template<typename T> T** matrixAllocate(int rows, int cols, T **M)
{
    M = new T*[rows];
    for (int i = 0; i < rows; i++){
        M[i] = new T[cols];
    }
    return M;
}

... 

int main()
{
    ...
    int** M1 = matrixAllocate<int>(rows, cols, M1);
    double** M2 = matrixAllocate(rows, cols, M2);
    ...
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top