سؤال

وكيف حيوي تخصيص مصفوفة 2D في C ++؟ لقد حاول بناء على ما سبق لي أن أعرف:

#include <iostream>

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

وكان يعمل لمعلمة واحدة، ولكن الآن لمدة سنتين. ماذا علي أن أفعل؟

هل كانت مفيدة؟

المحلول

ومصفوفة هو في الواقع مجموعة من المصفوفات.

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

وبطبيعة الحال، لحذف مصفوفة، يجب عليك القيام بما يلي:

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

ولقد برزت للتو احتمال آخر:

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

وتحرير هذه المجموعة أسهل:

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

وهذا الحل في الاستفادة من تخصيص كتلة كبيرة واحدة من الذاكرة لجميع العناصر، بدلا من عدة قطع صغيرة. الحل الأول نشرت لي هو أفضل مثال لل<م> صفائف صفائف مفهوم، وإن كان.

نصائح أخرى

ويمكنك أيضا استخدام std::vectors لتحقيق هذا:

وباستخدام std::vector< std::vector<int> >

مثال:

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

}

تعزيز :: 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];

إذا إما لا تمانع في بناء الجملة

arr[row * cols + col] = Aij;

وأو مشغل استخدام [] overaloading في مكان ما. وهذا قد يكون أكثر ودية ذاكرة التخزين المؤقت من مجموعة من المصفوفات، أو قد لا تكون، ربما أكثر يجب أن لا يهتمون بها. أريد فقط أن أشير إلى أن أ) مجموعة من المصفوفات ليست الحل الوحيد، ب) بعض العمليات أكثر سهولة لتنفيذ إذا مصفوفة تقع في كتلة واحدة من الذاكرة. منها مثلا.

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

وسطر واحد أقصر من

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

وعلى الرغم من إضافة صفوف لمثل هذه المصفوفة هو أكثر إيلاما

وأو يمكنك فقط تخصيص 1D مجموعة ولكن إشارة العناصر بطريقة 2D:

ولمعالجة الصف 2، العمود 3 (الزاوية اليسرى أعلى هو الصف 0، العمود 0):

وصول [2 * MATRIX_WIDTH + 3]

وحيث MATRIX_WIDTH هو عدد العناصر في صف واحد.

والجواب أخرى تصف صفائف صفائف صحيحة.
ولكن إذا كنت تخطط لتفعل أي شيء الرياضية مع المصفوفات - أو بحاجة إلى شيء خاص مثل المصفوفات متناثر يجب أن ننظر في واحدة من العديد من يبس الرياضيات مثل <وأ href = "http://math.nist.gov/tnt/overview هتمل "يختلط =" نوفولو noreferrer "> TNT قبل إعادة اختراع الكثير من العجلات

ولدي هذه الفئة الشبكة التي يمكن استخدامها في شكل مصفوفة بسيطة إذا كنت لا تحتاج إلى أي مشغلي الرياضية.

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

واستخدام مزدوج المؤشر هو إلى حد بعيد أفضل حل وسط بين سرعة التنفيذ / تحسين وضوح. باستخدام مجموعة واحدة لتخزين "محتويات المصفوفة هو في الواقع ما يقوم-مؤشر مزدوج.

ولقد استخدمت بنجاح قالب وظيفة الخالق التالية (نعم، وأنا أعلم أنا استخدم القديم الطراز C مؤشر المراجع، ولكنه جعل رمز أكثر وضوحا على الجانب الدعوة فيما يتعلق المعلمات تغيير - شيء يعجبني مؤشرات وهي غير ممكن مع المراجع سترى ما أعنيه):.

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

لإلغاء تخصيص الذاكرة التي تم إنشاؤها باستخدام الأداة المساعدة المذكورة أعلاه، واحدة ببساطة أن اجتثاث تخصيص في الاتجاه المعاكس.

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

لاستخدام هذه الوظائف قالب المذكورة أعلاه هو بعد ذلك من السهل جدا (على سبيل المثال):

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

وهنا هي الطريقة الأكثر واضحة وبديهية وأنا أعلم أن تخصص مجموعة 2D وديناميكية في C ++. قالب في هذا المثال تغطي جميع الحالات.

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);
    ...
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top