Как Вы динамично выделяете 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< 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];
Если вы не возражаете против синтаксиса
arr[row * cols + col] = Aij;
, либо где-нибудь примените перегрузку оператора []. Это может быть более удобным для кеширования, чем массив массивов, а может и нет, более вероятно, вам не стоит об этом заботиться. Я просто хочу отметить, что а) массив массивов - это не только решение, б) некоторые операции легче реализовать, если матрица находится в одном блоке памяти. Например,
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];
, хотя добавление строк в такую матрицу более болезненно
У меня есть класс сетки, который можно использовать как простую матрицу, если вам не нужны математические операторы.
/**
* 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;
}
или вы можете просто выделить 1D-массив, но ссылаться на элементы в 2D-режиме:
для адресации строки 2, столбца 3 (верхний левый угол - строка 0, столбец 0):
arr [2 * MATRIX_WIDTH + 3]
, где MATRIX_WIDTH - количество элементов в строке.
Другой ответ, описывающий массивы массивов, правильный.
НО, если вы планируете что-то математическое с массивами - или вам нужно что-то особенное, например, разреженные матрицы, вам следует взглянуть на одну из множества математических библиотек, таких как TNT , прежде чем изобретать слишком много колес