double arrow

Создание двуxмерного динамического массива

Операция new способна выделить память лишь под одномерный массив. А как быть, если массив двумерный?

Наиболее удобный способ - это представить двумерный массив как массив из массивов, т.е каждую строку матрицы - как одномерный массив. При этом под каждую строку матрицы память будет выделена по отдельности, как под одномерный массив; и на нее потребуется отдельный указатель. Поскольку строк в матрице может быть много, указателей тоже будет много, и уже для их хранения потребуется вспомогательный массив из указателей. А так как количество строк в матрице переменного размера заранее неизвестно, то этот вспомогательный массив тоже будет динамическим, и сначала нужно выделить память под него. Декларировать при этом придется только указатель на вспомогательный массив; он будет, таким образом, указателем на указатель (**).

Пример. Создать динамическую матрицу размера n1 х n2. Присвоить каждому ее элементу значение, равное сумме номеров его строки и столбца:

...

int **m, n1, n2;

puts("Vvedite chislo strok i stolbtsov");

scanf(“%d%d”, &n1, &n2);

m = new int * [n1]; // Захват памяти для массива указателей -

// на рисунке А (n1=3)

for (int i=0; i<n1; i++) // Захват памяти для каждого из

m[i] = new int [n2]; // массивов элементов (n1 таких массивов)

// - на рисунке B (n2=4)

...

for (i=0; i<n1; i++)

for (j=0; j<n2; j++)

m[i][j] = i+j; // *(*(m+i)+j) = i+j;

...

for (i=0; i<n1; i++) // Освобождение памяти

delete m[i];

delete m;

...

Устройство полученной "динамической матрицы" изображено на Рис. 19.1. Здесь имеется вспомогательный массив из 3 указателей и 3 массива для хранения данных, в каждом - по 4 элемента. Указатель m указывает на массив указателей, а каждый из указателей - на свою строку матрицы:

Ука­за­тели m[0] ® m[0][0] m[0][1] m[0][2] m[0][3] m[i][j] ↔ *(*(m+i)+j)
m[1] ® m[1][0] m[1][1] m[1][2] m[1][3]
m[2] ® m[2][0] m[2][1] m[2][2] m[2][3]

(А) (В)

Рис. 4

Несмотря на сложность полученной схемы, работа с ней предельно проста. Обращение к элементу матрицы имеет точно такой же вид, как и к элементу "обычного" двумерного массива:

m[i][j]

а выделение и освобождение динамической памяти для матрицы стандартно и не зависит от конкретной задачи:

m = new int * [n1]; // Выделение памяти

for (int i=0; i<n1; i++)

m[i] = new int [n2];

...

for (i=0; i<n1; i++) // Освобождение памяти

delete m[i];

delete m;

Преимущества динамических матриц:

1) Ее размер ограничен лишь размером доступной в данный момент памяти;

2) Под динамическую матрицу выделяется не больше памяти, чем требуется;

3) Ее строки могут быть не только одинаковой, но и разной длины (если нужно);

4) Чтобы поменять местами ее строки, не обязательно выполнять поэлементный обмен в цикле. Можно вместо этого переприсвоить указатели:

int *w=m[0];

m[0]=m[1];

m[1]=w;

Хотя все элементы матрицы остались на месте, 0-ая и 1-ая строки всё же поменялись местами, т.к. m[0] указывает теперь на бывшую 1-ую строку (и наоборот), и значение m[0][i] будет таким, каким до обмена было m[1][i].



Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



Сейчас читают про: