Aplicació: Operacions comuns sobre matrius

A continuació es presenten els exemples anàlegs als presentats a la lliçó de vectors ara pel cas de matrius. És molt recomanable que hagueu llegit prèviament els exemples de vectors abans de llegir aquests, ja que s’ometran alguns detalls per no ser massa repetitius.

En tota la lliçó suposarem que tenim la següent capçalera,

#include <iostream>
#include <vector>
using namespace std;

using vectorI = vector<int>;
using matriuI = vector<vectorI>;

i entendrem que les matrius amb les que treballarem tenen com a mínim una fila (encara que sigui buida), ja que si no no té sentit parlar de columnes i la crida int columnes = M[0].size() donaria problemes.

Suma de matrius

Una de les operacions més bàsiques que es poden fer entre matrius és sumarles. Com sabreu, per poder sumar dues matrius cal que aquestes tinguin les mateixes dimensions, i la suma es realitza element a element. Per comprovar que les dimesions coincideixen, podem fer ús d’asserts, com ja es va explicar a la lliçó del producte escalar, però ara no entrarem en aquest tema i suposarem que les matrius que entrem tenen les dimensions correctes. Així, una funció que retorna la matriu resultat de sumar dues matrius donades tindria el següent aspecte:

matriuI suma(const matriuI& A, const matriuI& B)
{
    int n = A.size();
    int m = A[0].size();
    matriuI C(n, vectorI(m));

    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            C[i][j] = A[i][j] + B[i][j];
        }
    }
}

Com ja s’ha explicat a la lliçó de matrius, ens interessa passar les matrius d’entrada per referència constant, per millorar l’eficiència del programa

Trobar la suma per files més gran

Hi ha molts exemples bàsics d’operacions amb matrius com trobar la suma dels seus elements, la mitjana, el valor i la posició de l’element més gran, etc. Però la majoria d’aquestes són exactament les mateixes que hem fet ja amb vectors, així que les ometrem i presentarem un exemple una mica diferent però senzill que barreja sumes i màxims.

En general, per calcular la suma de certs element donats creem una variable auxiliar inicialment nul·la a la que anem afegint els valors que volem sumar. Per altra banda, per trobar un màxim, creem una altra variable que en tot moment guarda l’element més gran que s’ha trobat fins ara i es va comparant amb els següents. Combinant ambdues estratègies, la nostra funció quedaria

int maxima_suma_fila(const matiruI& M)
{
    int n = M.size();
    int m = M[0].size();

    int sumaMaxima = 0;         // Una altra opció es inicialitzar el màxim a -inf
    for (int i = 0; i < n; ++i) {
        int sumaActual = 0;
        for (int j = 0; j < m; ++j) {
            sumaActual += M[i][j];    // Sumem els elements de la fila
        }
        if ((sumaActual > sumaMaxima) or (i == 0)) {
            sumaMaxima = sumaActual;  // Si superem el màxim o és la 1a fila, actualitzem.
        }
    }
    return sumaMaxima;
}

Transposar una matriu quadrada

És molt semblant a l’exemple de girar un vector. En aquest cas, els elements que voldrem intercanviar són el d’índex [i][j] amb el d’índex [n-1-i][n-1-j]. En aquest cas, el que hem de tenir en compte és que els elements de la diagonal no cal tocarlos i que només cal visitar una de les dues meitats separades per la diagonal, ja que en cas contrari recuperarem la matriu inicial perquè farem cada intercanvi dos cops. Així, l’acció quedaria

void transposa(matriuI& M) 
{
    int n = M.size();
    for (int i = 1; i < n; ++i) {          // Per cada fila
        for (int j = 0; j < i; ++j) {      // Pels elements per sota de la diagonal
            intercanvia(M[i][j], M[n-1-i][n-1-j]);
        }
    }
}

void intercanvia(int& a, int& b) 
{
    int c = a;
    a = b;
    b = c;
}

Comprovar si una matriu quadrada és simètrica

És pràcticament igual a l’exemple anterior, amb la diferència que en aquest cas no s’han de permutar els elements, sinó que s’han de comparar. La matriu serà simètrica si cada parella d’elements oposats són iguals, o dit d’una altra manera, si hi ha dos elements oposats diferents no serà una matriu simètrica. Recordeu que, tot i que en aquest cas no modificarem els valors de la matriu, no l’hem de passar per valor, ja que això farà que el programa sigui molt lent. El que feiem en aquests casos és passar la matriu per referència constant. Ens quedarà doncs la següent funció:

bool es_simetrica(const matriuI& M) 
{
    int n = M.size();
    for (int i = 1; i < n; ++i) {          // Per cada fila
        for (int j = 0; j < i; ++j) {      // Pels elements per sota de la diagonal
            if (M[i][j] != M[n-1-i][n-1-j]) {
                return false;              // Si hi ha 2 diferents NO és simètrica
            }
        }
    }
    return true;                           // Si no hi ha cap parella diferent és simètrica
}


Fòrum







Lliçons.jutge.org
Rafah Hajjar
Universitat Politècnica de Catalunya, 2019

Prohibit copiar. Tots els drets reservats.
No copy allowed. All rights reserved.