Fragment wykładu z mentorem w ramach kursu Codegym University. Zapisz się na pełny kurs.


"Witaj, Amigo!"

"Cześć Rysiu!"

„Wiesz już co nieco o tablicach i mam nadzieję, że udało ci się nawet rozwiązać niektóre zadania. Ale nie wiesz wszystkiego. Na przykład, oto kolejny interesujący fakt o tablicach. Tablice są nie tylko jednowymiarowe (liniowe ). Mogą być również dwuwymiarowe”.

"Um... Co to znaczy?"

„Oznacza to, że komórki tablicy mogą reprezentować nie tylko kolumnę (lub wiersz), ale także prostokątną tabelę.

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

„Gdzie nazwa to nazwa zmiennej tablicowej, szerokość to szerokość tabeli (w komórkach), a wysokość to wysokość tabeli. Spójrz na przykład:

int[][] data = new int[2][5];
data[1][1] = 5;
Tworzymy dwuwymiarową tablicę: 2 kolumny i 5 wierszy.
Piszemy 5 w komórce (1,1).

„Tak to będzie wyglądać w pamięci:

Tablice dwuwymiarowe

„Nawiasem mówiąc, w przypadku tablic dwuwymiarowych można również użyć szybkiej inicjalizacji:

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

„Hmm… to ciekawe. Jeśli wyobrazimy sobie, że w pierwszym nawiasy wewnętrzne reprezentują jeden element, następny jest drugim… Czyli tablica dwuwymiarowa jest jak tablica tablic?”

„Jaki z ciebie bystry uczeń! Dokładnie. Pierwszy element to jednowymiarowa tablica {31, 28, 31}, drugi to {30, 31, 30}, i tak dalej. Ale wrócimy do tego trochę później w tej lekcji. Do tego czasu spróbuj pomyśleć o dwuwymiarową tablicę jako tabelę z wierszami i kolumnami, tworzącą komórki na każdym przecięciu.

„Mam tego mentalny obraz. A tak przy okazji, do czego służą te dwuwymiarowe tablice?”

„Programista dość często potrzebuje dwuwymiarowych tablic. Jeśli przyjrzysz się uważnie, prawie każda gra planszowa jest zaimplementowana przy użyciu gotowej dwuwymiarowej tablicy: szachy, warcaby, kółko i krzyżyk, bitwa morska itp.:”

bitwa morska

„Rozumiem! Pole gry w szachy lub bitwę morską idealnie pasuje do dwuwymiarowych tablic!”

„Tak, ale musisz użyć liczb jako współrzędnych komórki. Nie 'pionek e2-e4', tylko 'pionek (5,2) -> (5,4)'. Tobie jako programiście będzie jeszcze łatwiej. "

Układanie elementów w tablice: (x, y) lub (y, x)

„Tworzenie tablic dwuwymiarowych rodzi interesujący dylemat. Kiedy tworzymy tablicę za pomocą new int [2][5];, czy mamy tabelę zawierającą „dwa wiersze i 5 kolumn ”, czy też „dwie kolumny i 5 wierszy”?

„Innymi słowy, nie jest do końca jasne, czy najpierw określamy szerokość, a potem wysokość… czy odwrotnie, najpierw wysokość, a potem szerokość?”

„Tak, to jest dylemat. I nie ma jednoznacznej odpowiedzi”.

"Co robić?"

„Po pierwsze, ważne jest, aby zrozumieć , w jaki sposób nasza dwuwymiarowa tablica jest faktycznie przechowywana w pamięci . Oczywiście pamięć komputera tak naprawdę nie zawiera żadnych tabel: każda lokalizacja w pamięci ma sekwencyjny adres numeryczny: 0, 1, 2, ... Dla nas jest to tabela 2 × 5, ale w pamięci to tylko 10 komórek, nic więcej. Bez podziału na wiersze i kolumny”.

„Rozumiem to. Jak więc określić, który wymiar jest pierwszy — szerokość czy wysokość?”

„Rozważmy pierwszą opcję. Najpierw szerokość, potem wysokość. Argument przemawiający za tym podejściem jest następujący: wszyscy uczą się matematyki w szkole i uczą się, że pary współrzędnych są zapisywane jako „x” (czyli oś pozioma). a następnie „y” (wymiar pionowy). I to nie jest tylko standard szkolny — to ogólnie przyjęty standard w matematyce. Jak to mówią, z matematyką nie można dyskutować”.

„Czy tak? Cóż, jeśli nie możemy z tym walczyć, to najpierw szerokość, a potem wysokość?”

"Istnieje ciekawy argument przemawiający za 'najpierw wysokość, potem szerokość' . Argument ten bierze się z szybkiej inicjalizacji tablic dwuwymiarowych. W końcu jeśli chcemy zainicjować naszą tablicę, to piszemy kod w ten sposób:"

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

„Więc co to dla nas robi?”

„Czy zauważyłeś coś? A jeśli mamy to?

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

„Jeśli zapiszemy nasze dane linia po linii kodu, otrzymamy tabelę z 2 wierszami i 5 kolumnami”.

„Teraz rozumiem. 2 to wysokość, a 5 to szerokość… Więc której opcji powinniśmy użyć?”

„To ty decydujesz, co jest wygodniejsze. Najważniejsze jest to, że wszyscy programiści pracujący nad tym samym projektem trzymają się tego samego podejścia”.

„Jeśli pracujesz nad projektem, którego kod ma wiele inicjowanych dwuwymiarowych tablic, to najprawdopodobniej wszystko będzie oparte na szybkiej inicjalizacji danych, czyli będziesz miał standardową „wysokość x szerokość”.

„Jeśli znajdziesz się w projekcie obejmującym dużo matematyki i pracy ze współrzędnymi (na przykład silniki gier), kod najprawdopodobniej przyjmie podejście„ szerokość x wysokość ”.

Jak rozmieszczone są tablice dwuwymiarowe

„Teraz, czy pamiętasz szczególną cechę tablic dwuwymiarowych, którą zauważyłeś na początku lekcji?”

„Tak! Chodziło o to, że tablice dwuwymiarowe są w rzeczywistości tablicami tablic!”

„Zgadza się. Innymi słowy, jeśli w przypadku zwykłej tablicy zmienna tablicowa przechowuje odniesienie do kontenera przechowującego elementy tablicy, to w przypadku tablic dwuwymiarowych sytuacja nieco eksploduje: -array zmienna przechowuje odniesienie do kontenera, który przechowuje odniesienia do jednowymiarowych tablic. Lepiej zobaczyć to raz w akcji, niż próbować wyjaśniać to sto razy:

Jak rozmieszczone są tablice dwuwymiarowe

„Po lewej stronie mamy dwuwymiarową zmienną tablicową, która przechowuje odniesienie do dwuwymiarowego obiektu tablicowego. W środku znajduje się dwuwymiarowy obiekt tablicowy, którego komórki przechowują jednowymiarowe tablice, które są wiersze dwuwymiarowej tablicy. Po prawej stronie widać cztery jednowymiarowe tablice — wiersze naszej dwuwymiarowej tablicy. Tak właśnie działają dwuwymiarowe tablice”.

„Fantastycznie! Ale co nam to daje?”

Ponieważ „kontener kontenerów” przechowuje odniesienia do „tablic wierszy”, możemy bardzo szybko i łatwo zamienić wiersze. Aby uzyskać „kontener kontenerów”, wystarczy określić jeden indeks zamiast dwóch. Przykład:

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

„Spójrz na poniższy kod. Możemy go użyć do zamiany wierszy:”

// 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;
Tablica dwuwymiarowa





matrix[0]przechowuje odniesienie do pierwszego wiersza.
Wymieniamy referencje.

W rezultacie matrixtablica wygląda następująco:
{
  {5, 4, 3, 2, 1},
  {1, 2, 3, 4, 5}
};

„Rozumiem. To działa jak zamiana dowolnych dwóch zwykłych przedmiotów”.

„Tak jest. Cóż, jeśli odwołujesz się do komórki dwuwymiarowej tablicy, ale podajesz tylko jeden indeks po nazwie tablicy, to odnosisz się do kontenera kontenerów, którego komórki przechowują odniesienia do zwykłych... tablice wymiarowe”.

„Wszystko wydaje się logiczne i jasne. Dzięki za wykład, Rishi!”

„Nie ma za co. Wcielaj to w życie mądrze”.