Matrici (Tablouri Bidimensionale)
Noțiuni de bază
Declarare, citire, afișare și parcurgeri elementare pe matrici.
Declarare, inițializare și accesul la elemente
O matrice este un tablou bidimensional -- un tabel cu linii si coloane. In C++ o declaram cu doua dimensiuni.
Declarare
int m[100][100]; // matrice de maxim 100 linii si 100 coloaneDimensiunile se aleg in functie de enunt. Daca enuntul spune "cel mult N linii si M coloane", declari m[N+1][M+1] sau direct cu o valoare sigura ca 100 sau 1001.
Liniile si coloanele se numeroteaza de obicei de la 1 la BAC, deci declari cu un rand/coloana in plus si ignori indicele 0.
int m[101][101]; // linii 1..100, coloane 1..100
int n, p; // n = nr linii, p = nr coloaneAccesul la un element
m[i][j] este elementul de pe linia i, coloana j.
m[1][1] = 5; // primul element (linia 1, coloana 1)
m[i][j] = 0; // elementul de pe linia i, coloana j
cout << m[2][3]; // afiseaza elementul de pe linia 2, coloana 3Matrice patratica
O matrice cu n linii si n coloane se numeste patratica. La BAC apar frecvent matrici patratice -- diagonalele, zonele si simetria se definesc pe ele.
int n;
int m[101][101]; // matrice patratica n x nInitializare cu 0
int m[101][101] = {0}; // toate elementele 0 la declarareSau in timpul executiei:
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
m[i][j] = 0;Citirea și afișarea unei matrici
Citire
Citim elementele linie cu linie, coloana cu coloana:
int n, p;
int m[101][101];
cin >> n >> p; // n = nr linii, p = nr coloane
for (int i = 1; i <= n; i++)
for (int j = 1; j <= p; j++)
cin >> m[i][j];Afisare
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= p; j++) {
cout << m[i][j];
if (j < p) cout << " "; // spatiu intre elemente, nu dupa ultimul
}
cout << endl; // linie noua dupa fiecare rand
}Sau mai simplu (cu spatiu si dupa ultimul element -- acceptat la BAC):
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= p; j++)
cout << m[i][j] << " ";
cout << endl;
}Matrice patratica -- citire si afisare
La matricea patratica avem un singur n:
int n;
int m[101][101];
cin >> n;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
cin >> m[i][j];
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++)
cout << m[i][j] << " ";
cout << endl;
}Ordinea for-urilor conteaza
Mereu: for linie, for coloana -- asa parcurgem rand cu rand, exact cum sunt stocate in memorie si cum sunt citite/afisate datele.
for (int i = 1; i <= n; i++) // linie
for (int j = 1; j <= p; j++) // coloana
// m[i][j]Cum se misca i si j -- exemplu pentru n=3, p=4
Pornind cu i=1, j=1, j avanseaza pana la capat, apoi i creste si j se reintoarce la 1:
j=1 j=2 j=3 j=4
i=1 m[1][1] m[1][2] m[1][3] m[1][4] <- for-ul interior parcurge toata linia 1
i=2 m[2][1] m[2][2] m[2][3] m[2][4] <- apoi toata linia 2
i=3 m[3][1] m[3][2] m[3][3] m[3][4] <- si toata linia 3Ordinea exacta a vizitarii elementelor:
pas 1: i=1, j=1 => m[1][1]
pas 2: i=1, j=2 => m[1][2]
pas 3: i=1, j=3 => m[1][3]
pas 4: i=1, j=4 => m[1][4] <- j a ajuns la capat, i creste
pas 5: i=2, j=1 => m[2][1] <- j reincepe de la 1
pas 6: i=2, j=2 => m[2][2]
pas 7: i=2, j=3 => m[2][3]
pas 8: i=2, j=4 => m[2][4] <- j a ajuns la capat, i creste
pas 9: i=3, j=1 => m[3][1] <- j reincepe de la 1
pas 10: i=3, j=2 => m[3][2]
pas 11: i=3, j=3 => m[3][3]
pas 12: i=3, j=4 => m[3][4] <- gataNotă: Regula simpla: j se misca repede (loop interior), i se misca incet (loop exterior). Cand j termina un tur complet, i avanseaza cu 1 si j se reintoarce la inceput.
Ce se intampla daca inversezi for-urile?
Daca scrii for j exterior si for i interior, parcurgi coloana cu coloana in loc de linie cu linie:
j=1 j=2 j=3 j=4
i=1 m[1][1] m[1][2] m[1][3] m[1][4]
i=2 m[2][1] m[2][2] m[2][3] m[2][4]
i=3 m[3][1] m[3][2] m[3][3] m[3][4]
Ordinea cu j exterior:
m[1][1], m[2][1], m[3][1], <- coloana 1
m[1][2], m[2][2], m[3][2], <- coloana 2
m[1][3], m[2][3], m[3][3], <- coloana 3
m[1][4], m[2][4], m[3][4] <- coloana 4La citire si afisare aceasta ordine este gresita -- datele se citesc linie cu linie din input, nu coloana cu coloana. La unele operatii (de ex. suma tuturor elementelor) ordinea nu conteaza, dar la citire/afisare conteaza intotdeauna.
Parcurgeri elementare: sumă, min, max, numărare
Suma tuturor elementelor
long long suma = 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= p; j++)
suma += m[i][j];
cout << suma;Minimul si maximul din matrice
int minim = m[1][1], maxim = m[1][1];
for (int i = 1; i <= n; i++)
for (int j = 1; j <= p; j++) {
if (m[i][j] < minim) minim = m[i][j];
if (m[i][j] > maxim) maxim = m[i][j];
}
cout << minim << " " << maxim;Numararea elementelor cu o proprietate
int cnt = 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= p; j++)
if (m[i][j] % 2 == 0) // de exemplu, numara elementele pare
cnt++;
cout << cnt;Verificarea unei conditii pentru toate elementele
bool toate_pozitive = true;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= p; j++)
if (m[i][j] <= 0) {
toate_pozitive = false;
break;
}
if (toate_pozitive) cout << "DA";
else cout << "NU";Notă: Dupabreakiesi doar din for-ul interior. Daca vrei sa iesi din ambele for-uri, foloseste o variabila flag saugoto(dar la BAC e mai elegant cu flag).
Cautarea unui element
int val;
cin >> val;
bool gasit = false;
int lin_gasit, col_gasit;
for (int i = 1; i <= n && !gasit; i++)
for (int j = 1; j <= p && !gasit; j++)
if (m[i][j] == val) {
gasit = true;
lin_gasit = i;
col_gasit = j;
}
if (gasit) cout << "Gasit la linia " << lin_gasit << ", coloana " << col_gasit;
else cout << "Nu exista";