Фрагмент от лекция с ментор като част от курса на Codegym University. Запишете се за пълния курс.


„Поздрави, амиго!“

„Здравей, Риши!“

„Вече знаете нещо or две за масивите и дори успяхте да решите някои задачи, надявам се. Но не знаете всичко. Например, ето още един интересен факт за масивите. Масивите не са само едномерни (линейни ). Те могат да бъдат и двуизмерни."

— Хм... Какво означава това?

„Това означава, че клетките на масива могат да представляват не само колона (or ред), но и правоъгълна table.

int[][]name = new int[width][height];

„Където name е името на променливата на масива, width е ширината на tableта (в клетки), а height е височината на tableта. Погледнете пример:

int[][] data = new int[2][5];
data[1][1] = 5;
Създаваме двуизмерен масив: 2 колони и 5 реда.
Пишем 5 в клетка (1,1).

„Ето How ще изглежда в паметта:

Двумерни масиви

„Между другото, за двумерни масиви можете също да използвате бърза инициализация:

// Lengths of months of the year in each quarter
int[][] months = { {31, 28, 31}, {30, 31, 30}, {31, 31, 30}, {31, 30, 31} };

"Хм... това е интересно. Ако си представим, че първите вътрешни скоби представляват един елемент, следващите са втори... Значи двумерният масив е като масив от масиви?"

„Какъв умен ученик си! Точно така. Първият елемент е едномерният масив {31, 28, 31}, вторият е {30, 31, 30}и така нататък. Но ще се върнем към това малко по-късно в този урок. Дотогава се опитайте да мислите за двуизмерен масив като table с редове и колони, образуващи клетки на всяко пресичане.

„Имам умствена картина за това. Между другото, за Howво се използват тези двуизмерни масиви?“

„Програмистите се нуждаят от двуизмерни масиви доста често. Ако се вгледате внимателно, почти всяка настолна игра се реализира с помощта на готов двуизмерен масив: шах, дама, тик-так, морска битка и т.н.:“

морска битка

„Разбрах! Игралното поле на шах or морска битка се вписва идеално в двуизмерни масиви!“

„Да, но трябва да използвате числа като координати на клетката. Не „пешка e2-e4“, а „пешка (5,2) -> (5,4)“. Ще ви бъде още по-лесно като програмист. "

Подреждане на елементи в масиви: (x, y) or (y, x)

„Създаването на двуизмерни масиви повдига интересна дилема. Когато създаваме масив с помощта на new int [2][5];, имаме ли table с „два реда и 5 колони “ or е „две колони и 5 реда“?“

„С други думи, не е съвсем ясно дали първо определяме ширината и след това „височината... or обратното, първо височината и след това ширината?“

"Да, това е дилемата. И няма категоричен отговор."

"Какво да правя?"

„Първо, важно е да разберем How нашият двуизмерен масив всъщност се съхранява в паметта . Естествено компютърната памет всъщност няма ниHowви таблици в нея: всяко място в паметта има последователен цифров address: 0, 1, 2, ... За нас това е table 2 × 5, но в паметта е само 10 клетки, нищо повече. Без разделение на редове и колони.“

"Разбрах това. Как тогава да определим кое измерение е първо - ширината or височината?"

„Нека разгледаме първия вариант. Първо ширината, след това височината. „Аргументът в полза на този подход е следният: всеки учи математика в учorще и научава, че координатните двойки се записват като „x“ (тоест хоризонталната ос) и след това 'y' (вертикалното измерение). И това не е просто учorщен стандарт - това е общоприет стандарт по математика. Както се казва, с математиката не се спори“.

"Така ли? Е, ако не можем да се борим, тогава първо ширината и след това височината?"

„Има интересен аргумент в полза на „първо височината, след това ширината“ . Този аргумент идва от бързата инициализация на двумерни масиви. В крайна сметка, ако искаме да инициализираме нашия масив, тогава пишем code по следния начин:“

// Matrix of important data
int[][] matrix = { {1, 2, 3, 4, 5}, {1, 2, 3, 4, 5} };

„И така, Howво ни прави това?“

„Забелязахте ли нещо? Ами ако имаме това?

// Matrix of important data
int[][] matrix = {
  {1, 2, 3, 4, 5},
  {1, 2, 3, 4, 5}
};

„Ако запишем нашите данни в codeа ред по ред, тогава ще получим table с 2 реда и 5 колони.“

„Сега разбирам. 2 е височината, а 5 е ширината... Тогава коя опция да използваме?“

"От вас зависи да решите кое е по-удобно. Най-важното е всички програмисти, работещи по един и същ проект, да се придържат към един и същ подход."

„Ако работите върху проект, чийто code има много инициализирани двуизмерни масиви, тогава най-вероятно всичко там ще се основава на бърза инициализация на данни, т.е. ще имате стандартната „височина x ширина“.

„Ако попаднете в проект, включващ много математика и работа с координати (например двигатели за игри), тогава codeът най-вероятно ще възприеме подхода „ширина х височина“.

Как са подредени двумерните масиви

„Сега, спомняте ли си специалната характеристика на двумерните масиви, която забелязахте в началото на урока?“

"Да! Беше, че двумерните масиви всъщност са масиви от масиви!"

„Съвсем правилно.“ С други думи, ако в случай на обикновен масив променливата на масива съхранява препратка към контейнер, който съхранява елементи на масив, тогава в случая на двумерни масиви ситуацията се взривява малко: двумерен масив -array променлива съхранява препратка към контейнер, който съхранява препратки към едномерни масиви. По-добре е да го видите в действие веднъж, instead of да се опитвате да го обяснявате сто пъти:"

Как са подредени двумерните масиви

„Отляво имаме променлива с двуизмерен масив, която съхранява препратка към обект с двуизмерен масив. В средата има обект с двуизмерен масив, чиито клетки съхраняват едномерни масиви, които са редове от двуизмерен масив. А отдясно можете да видите четири едномерни масива — редовете на нашия двуизмерен масив. Ето How всъщност работят двуизмерните масиви."

"Фантастично! Но Howво ни дава?"

„Тъй като „контейнер от контейнери“ съхранява препратки към „масиви от редове“, можем много бързо и лесно да разменяме редове. За да получите „контейнер от контейнери“, просто трябва да посочите един индекс instead of два. Пример:

int[][] data = new int[2][5];
int[] row1 = data[0];
int[] row2 = data[1];

„Вижте codeа по-долу. Можем да го използваме за размяна на редове:“

// Matrix of important data
int[][] matrix = {
  {1, 2, 3, 4, 5},
  {5, 4, 3, 2, 1}
};

int[] tmp = matrix[0];
matrix[0] = matrix[1];
matrix[1] = tmp;
Двумерният масив





matrix[0]съхранява препратка към първия ред.
Разменяме референциите.

В резултат на matrixтова масивът изглежда така:
{
  {5, 4, 3, 2, 1},
  {1, 2, 3, 4, 5}
};

„Разбрах. Работи като размяна на два обикновени предмета.“

„Така е така. Е, ако се позовавате на клетка от двумерен масив, но посочите само един индекс след името на масива, тогава вие се позовавате на контейнер от контейнери, чиито клетки съхраняват препратки към обикновени едно- размерни масиви."

„Всичко изглежда логично и ясно. Благодаря за лекцията, Риши!“

„Заповядайте. Приложете го на практика мъдро.“