Как изменить класс массива Dynamic Safe 2D на класс динамических безопасных 2D-зубчатых массивов? Я прочитал статью, лучше и безопаснее использовать динамически безопасный или динамически безопасный 2D-массив, чтобы избежать инициализации массива размером меньше 0 или массива размером больше его исходного размера. В большинстве случаев мы можем столкнуться с такими проблемами с чрезмерной рекурсией, как использование обратного отслеживания для поиска пути лабиринта. Итак, я пытался реализовать динамический безопасный класс 2D-зубчатых массивов, но я не понимаю, как мне его реализовать?
//Dynamic Safe 2D array class
template <class T>
class DS2DA
{
private:
T **Data;
int nRow;
int nCol;
public:
DS2DA ()
{
nRow=0;
nCol=0;
Data=nullptr;
}
DS2DA (int nRow,int nCol)
{
this->nRow=nRow;
this->nCol=nCol;
Data=new T * [nRow];
for (int i=0;i<nRow;i++)
{
Data[i]=new T [nCol];
}
for (int i=0;i<nRow;i++)
{
for (int j=0;j<nCol;j++)
{
Data[i][j]=0;
}
}
}
T & operator () (int n1,int n2)
{
if ((n1<0 or n1>this->nRow) or (n2<0 or n2>this->nCol))
{
cout<<"Array out of bound";
exit (1);
}
else
return (Data[n1][n2]);
}
};
//Driver Program
int main ()
{
DS2DA <double> obj1 (3,3);
int input;
for (int i=0;i<3;i++)
{
cout<<"Row "<<i+1<<endl;
for (int j=0;j<3;j++)
{
cout<<"Enter Element "<<j+1<<":";
cin>>input;
obj1 (i,j)=input;
}
}
}
Я почти уверен, что упускаю суть, но, как писал в своем комментарии Меч-рыба std::vector
содержащий std::vector
с должен сделать трюк.
Если вам нужен двумерный массив с ограничением ширины и высоты, который динамически увеличивается, попробуйте следующий код:
template<class T>
class DynamicArray
{
public:
DynamicArray()
: rowCount(0),
colCount(0)
{}
DynamicArray(size_t rowCount_, size_t colCount_)
: rowCount(rowCount_),
colCount(colCount_)
{}
const T& operator()(size_t row, size_t col) const
{
if (row >= rowCount || col >= colCount)
throw std::out_of_range("Row or column index out of range in " __FUNCTION__);
static const T empty;
if (data.size() <= row)
return empty;
const auto& rowData = data[row];
if (rowData.size() <= col)
return empty;
return rowData[col];
}
T& operator()(size_t row, size_t col)
{
if (row >= rowCount || col >= colCount)
throw std::out_of_range("Row or column index out of range in " __FUNCTION__);
if (data.size() <= row)
data.resize(row + 1);
auto& rowData = data[row];
if (rowData.size() <= col)
rowData.resize(col + 1);
return rowData[col];
}
public:
std::vector<std::vector<T>> data;
size_t rowCount, colCount;
};
Массив всегда начинается без каких-либо строк или столбцов, но с ограничением строки / столбца (устанавливается в 0 в конструкторе по умолчанию).
Оба оператора () в основном делают одно и то же: проверяют индекс строки и столбца и возвращают соответствующую ячейку. Однако, в то время как неконстантный оператор () изменяет размер зубчатого массива для хранения данного элемента, const оператор () просто возвращает ссылку на пустой (созданный по умолчанию) элемент. Таким образом, вы не создаете излишне все недостающие элементы при переборе массива.
Возможно, unordered_map с парой координат в качестве индекса даст вам еще лучшие результаты в зависимости от варианта использования. Вы можете объявить это с std::unordered_map<std::pair<int, int>, T>
, Пара целых должна привести к довольно быстрой функции хеширования. С очень разреженным массивом это было бы моим предпочтительным решением.
Помните, что использование __FUNCTION__
может потребоваться изменить (или пропустить), если вы не используете Visual Studio. (в gcc __FUNCTION__
расширяется до функции, которая возвращает имя функции, в то время как Visual Studio расширяет его до строки, содержащей имя текущей функции).
Других решений пока нет …