Jako tablicę dwuwymiarową możemy sobie wyobrazić planszę prostokątną składającą się z pewnej liczby wierszy i kolumn (indeksowanie rozpoczynamy od zera). Aby przypisać lub pobrać wartość do danej komórki, należy podać jej obie współrzędne.
Inicjacja tablicy polega na podaniu ilości wierszy i kolumn:
typ_elementów_tablicy nazwa_tablicy [ ilość wierszy ][ ilość kolumn ];
np.:
//stworzenie dwuwymiarowej tablicy liczb całkowitych, w sumie 100 komórek: 10x10.
int tab [ 10 ][ 10 ];
Wartości początkowe tablicy możemy nadać przy jej deklaracji. Popatrzmy na przykład oparty na tablicy dwuwymiarowej liczb całkowitych:
//zauważmy, że mamy trzy wiersze, i dwie kolumny
int tab[3][2] = {{1,3},{4,5},{0,-1}};
Przy nadawaniu wartości tablicy można pominąć wartość w pierwszym nawiasie kwadratowym:
//wartość pierwszego nawiasu została pominięta
int tab[][2] = {{1,3},{4,5},{0,-1}};
Aby odwołać się do każdej z komórek należy w nawiasach kwadratowych podać numer wiersza i kolumny komórki, do której się odwołujemy, pamiętając o tym, że numerujemy je od zera:
int tab[][2] = {{1,3},{4,5},{0,-1}}; //deklaracja i inicjacja tablicy dwuwymiarowej
cout<<tab[2][1]; //wyświetlenie wartości komórki znajdującej się w trzecim wierszu i w drugiej kolumnie (-1)
tab[0][0] = -100; //przypisanie do pierwszej komórki wartości -100
Jeśli wielkość tablicy zależy od pewnych czynników, na przykład podajemy z klawiatury jej wielkość, lub ograniczenia stosu nie pozwalają nam na stworzenie odpowiednio dużej tablicy, to możemy przydzielić pamięć na nią dynamicznie (pobrać pamięć ze sterty):
int **tab, k, w;
cout<<"Podaj liczbę wierszy i kolumn w tablicy: ";
cin>>w>>k;
tab = new int *[w]; //przydzielenie pamięci na w wierszy
for(int i=0;i<w;i++)
tab[i] = new int[k]; //przydzielenie dla każdego wiersza po k komórek
//instrukcje własciwe programu
//zwolnienie pamięci
for(int i=0;i<w;i++)
delete [] tab[i];
delete [] *tab;
Warto przy okazji zauważyć, że liczba komórek w każdym wierszu może mieć różną wartość, czyli tablica dwuwymiarowa nie musi być prostokątna:
int **tab, k, w;
cout<<"Podaj liczbę wierszy: ";
cin>>w;
tab = new int *[w]; //przydzielenie pamięci na w wierszy
for(int i=0;i<w;i++)
{
cout<<"Podaj liczbę komórek w wierszu o numerze "<<i<<": ";
cin>>k;
tab[i] = new int[k]; //przydzielenie dla każdego wiersza po k komórek
}
//instrukcje własciwe programu
//zwolnienie pamięci
for(int i=0;i<w;i++)
delete [] tab[i];
delete [] *tab;
Napisz program, który wykona transpozycję macierzy 4x5. Liczby generujemy losowo z przedziału [-9; 9]. Elementami macierzy są liczby całkowite.
Rozwiązanie
Macierz to obiekt, który doskonale nadaje się do przechowywania w tablicach dwuwymiarowych. Każda macierz składa się z pewnej ilości wierszy i kolumn. Przykładowa macierz spełniająca warunki zadania:
$$\begin{bmatrix} 1 & 1 &- 5 & 8 & 2\\ 2 & 2 & 0 & 0 & 5\\ 3 & 3 & 6 & -6 & 4\\2 & 4 & 5 & -9 & -8 \end{bmatrix}$$
Transpozycja macierzy polega na zamianie wierszy z kolumnami. Powyższa macierz powinna wyglądać następująco:
$$\begin{bmatrix} 1 & 2 & 3 & 2\\ 1 & 2 & 3 & 4\\ -5 & 0 & 6 & 5\\8 & 0 & -6 & -9\\2 & 5 & 4 & -8\end{bmatrix}$$
#include<iostream>
using namespace std;
int main()
{
int tab[4][5]
cout<<"Przed transpozycją:\n ";
for(int i=0;i<4;i++)
{
for(int j=0;j<5;j++)
{
//wygenerowanie liczb z zakresu [-9; 9]
tab[i][j]=rand()%19-9;
//wyświetlenie wylosowanej liczby
cout<<tab[i][j]<<" ";
}
cout<<endl;
}
//transpozycja macierzy
cout<<"Po transpozycji: "<<endl;
for(int i=0;i<5;i++)
{
for(int j=0;j<4;j++)
cout<<tab[j][i]<<" ";
cout<<endl;
}
return 0;
}
Jeśli chcemy wyzerować tablicę (ustawić wszystkie jej komórki na wartość $$0$$, możemy to zrobić przy jej definiowaniu:
int tab[5][5] = {};
Taka konstrukcja zadziała tylko przy tworzeniu tablicy. Jeśli chcemy ponownie ją wyzerować musimy posłużyć się pętlami (w przypadku dwuwymiarowej tablicy będą dwie zagnieżdżone pętle):
int tab[100][23];
for(int i=0;i<100;i++)
for(int j=0;j<23;j++)
tab[i][j]=0;
Jeśli tablicę zadeklarujemy jako globalną, także zostanie wyzerowana:
#include<iostream>
using namespace std;
int tab[100][23]; //wszystkie elementy są wyzerowane
int main()
{
// ciało funkcji main()
return 0;
}
Tablice o większej liczbie wymiarów rzadko się stosuje. Sposób inicjacji, oraz operowania na tablicach tego typu jest analogiczny jak w przypadku tablic dwuwymiarowych.
Prześledźmy przykład tworzenia tablicy trójwymiarowej:
#include<iostream>
using namespace std;
int main()
{
//deklaracja tablicy trójwymiarowej
//taka tablica posiada 3*4*5 = 60 komórek
int tab[3][4][5];
//przypisanie wartości 23 do pierwszej komórki
tab[0][0][0] = 23;
cout<<tab[0][0][0]<<endl;
return 0;
}
Odwołując się do komórek tablicy trójwymiarowej, możemy sobie wyobrazić, że odwołujemy się to jednostkowych sześcianów, z których zbudowany jest prostopadłościan. Aby "dostać się" do danego sześcianu, musimy określić jego współrzędne: długość, szerokość oraz wysokość.