You are on page 1of 17

Operaciones con matrices – Clase Matriz en 

c++
El siguiente es el primer ejercicio que hice con matrices. Quizás alguno de estos ejercicios
te puedan servir como una base. Puedes leer el post anterior sobre vectores, matrices y
punteros si aún no haz trabajo con ellos.

Recomiendo que intentes y practiques mucho antes de copiar y pegar. Si te sientes


estancado en algún problema recién trata de buscar una guía para llegar a la solución.

Esta clase matriz tendrá 3 atributos: Matriz,número de filas y número de columnas. Tiene
un constructor por defecto,constructor copiador y un constructor por parámetro que recibe
el número de filas y columnas.

Las siguientes funciones fueron implementadas:

 Generar una matriz dinámicamente


 LLenar la matriz desde teclado:
 Llenar la matriz aleatoriamente:
 Imprimir la matriz
 Hallar el mayor elemento.
 Hallar el menor elemento.
 Hallar la moda.
 Intercambiar filas.
 Intercambiar columnas.
 Sumar otra matriz: Sumar 2 objetos de tipo matriz retornar otra matriz. Ejem: c = a
+ b.
 Restar otra matriz: Igual que la suma. Ejem: c= a – b
 Multiplicar por otra matriz: Ejem: c = a * b. El nro de filas de a debe ser igual al nro
de columnas de b
 Multiplicar por un escalar: Ingreso un número y todos los elementos de la matriz se
multiplican por ese número.
 Hallar matriz transpuesta: matr[m][n] su transpuesta es matr[n][m]. Se obtiene
cambiando filas por columnas. Donde los elementos de la fila m ahora pertenecen a
la columna m de la transpuesta.
 Verificar si es simétrica: Una matriz es simétrica si es cuadrada(filas=columnas) y
cuando su transpuesta es igual a su matriz original.
 Verificar si es identidad: Es identidad si tiene todos sus elementos nulos excepto los
de la diagonal principal que son iguales a 1.

NOTA: He aplicado un poco de templates para manejar la matriz con varios tipos de datos
(int, float, char,double) y sobrecarga de operadores para la suma, resta y multiplicación de
matrices.
Recien estoy aprendiendo a usar estas 2 características importantes del lenguaje (templates
y sobrecarga de operadores) por lo tanto, estos temas serán tratados a profundidad el
proximo año.

En breve:

Un template es una manera de que funciones, clases métodos puedan ser usados con varios
tipos de datos. Imagínense crear una lista de datos y tener que crear funciones insertar,
eliminar, buscar, concatenar, etc para cada tipo de dato. Si los métodos y la clase tienen la
misma lógica para que reescribir código si podemos reutilizar.

La sobrecarga de operadores es una manera de realizar las mismas operaciones que solemos
hacer con tipos de datos comunes con tipos abstractos de datos. Por ejemplo, la sobrecarga
me permitió sumar 2 objetos de tipo Matriz y almacenar el resultado en otro objeto Matriz,
del modo c = a + b

Al grano:

Definición de la clase Matriz (La cabecera o header):

matriz.h

view source
print?
01 #ifndef MATRIZ_H
02 #define MATRIZ_H
03  
04 #include <iostream>
05 #include <time.h>
06  
07 using namespace std;
08  
09 template <class T>
10 class Matriz

11 {
12   private:
13     T mayor_,menor_,moda_,ele,**matr1;
14     int dim_matriz;

15   public:
16     int fils,cols;
17     T escalar;
18  
19     Matriz();
20     Matriz(int,int);
21     Matriz(const Matriz &m);//constructor copia
22  
23     void llenar_teclado();
24     void llenar_aleatorio();
25     void imprimir();
26  
27     T mayor();
28     T menor();
29     T moda();
30  
31     void inter_filas(int,int);
32     void inter_cols(int,int);

33  
34     bool esSimetrica();
35     bool esIdentidad();
36     void multi_escalar(T);
37     void transpuesta();
38  
39     Matriz<T> operator+ (const Matriz &matr2);
40     Matriz<T> operator- (const Matriz &matr2);
41     Matriz<T> operator* (const Matriz &matr2);
42  
43     void eliminar();
44  
45     ~Matriz();
46     protected:
47 };
48  
49 #endif // MATRIZ_H

Implemetanción de la clase:

matriz.cpp
view source
print?
001 #include "Matriz.h"
002  
003 //Constructor por defecto
004 template<typename T>
005 Matriz<T>::Matriz()
006 {
007   fils=4;
008   cols=4;
009 }
010  
011 //Constructor copia
012 template<typename T>
013 Matriz<T>::Matriz(const Matriz &m)
014 {
015   *this = m;
016 }

017  
018 //Constructor por parametro
019 template<typename T>
020 Matriz<T>::Matriz(int fils_ , int cols_)
021 {
022   fils = fils_;
023   cols = cols_;
024   matr1 = new T*[fils];
025   for(int i=0;i<fils;i++){
026       matr1[i] = new T[cols];
027   }
028 }

029  
030 //Llenar aleatoriamente una matriz
031 template<typename T>
032 void Matriz<T>::llenar_aleatorio()
033 {
034   //srand(time(NULL));
035   for(int i=0;i<fils;i++){
036     for(int j=0;j<cols;j++){
037       matr1[i][j] = rand() % 30;
038     }

039   }
040   mayor_= matr1[0][0];
041   menor_= matr1[0][0];
042   srand(time(NULL));
043 }
044  
045 //Llenar una matriz desde teclado
046 template<typename T>
047 void Matriz<T>::llenar_teclado()
048 {

049   for(int i=0;i<fils;i++){


050     cout << "Fila " << i+1 << endl;
051     for(int j=0;j<cols;j++){
052       cout << "Ingresa el elemento " << j+1 << endl;
053       cin >>ele;
054       matr1[i][j] = ele;
055     }
056     cout << endl;
057   }
058   mayor_= matr1[0][0];
059   menor_= matr1[0][0];
060 }

061  
062 //Imprimir matriz
063 template<typename T>
064 void Matriz<T>::imprimir()
065 {
066   for(int i=0;i<fils;i++){
067     for(int j=0;j<cols;j++){
068       cout << matr1[i][j] << " ";
069     }
070     cout << endl << endl;
071   }
072   cout << endl << endl;
073 }
074  
075 //Obtener el mayor de la matriz
076 template<typename T>
077 T Matriz<T>::mayor()
078 {

079   for(int i=0;i<fils;i++){


080     for(int j=0;j<cols;j++){
081       if(matr1[i][j] > mayor_){
082         mayor_ = matr1[i][j];
083       }
084     }

085   }
086   return mayor_;
087 }
088  
089 //Obtener el menor de la matriz
090 template<typename T>
091 T Matriz<T>::menor()
092 {

093   for(int i=0;i<fils;i++){


094     for(int j=0;j<cols;j++){
095       if(matr1[i][j] < menor_){
096         menor_ = matr1[i][j];
097       }
098     }

099   }
100   return menor_;
101 }
102  
103 //Obtener la moda de la matriz
104 template<typename T>
105 T Matriz<T>::moda()
106 {
107   //creo una matriz auxiliar
108   Matriz maux(fils,cols);

109  
110   //lleno la matriz con ceros
111   for(int i=0;i<fils;i++){
112     for(int j=0;j<cols;j++){
113       maux.matr1[i][j] = 0;
114     }
115   }
116  
117   dim_matriz = fils * cols;
118   int y=0;//para retener una fila n veces
119   int z=0;//para retener una columna n veces
120  
121   //empiezo a comparar cada elemento n veces
122   for(int x=0;x<dim_matriz;x++){

123     for (int i = 0; i < fils; i++){


124       for (int j = 0; j < cols; j++){
125         if(matr1[y][z] == matr1[i][j]){
          maux.matr1[i][j]++;//incremento en 1 el valor de la matriz
126
aux en esa posicion
127         }
128       }

129     }
130     //pasar a la siguiente columna despues de n comparaciones
131     z++;
132     if(z==cols){//empiezo a comparar con la siguiente fila
133       z=0;//empiezo nuevamente en la 1era columna
134       y++;//paso a la siguiente fila
135     }
136   }

137  
138   //obtengo el valor mayor de la matriz
139   mayor_ = maux.mayor();
140  
  if(mayor_==1){//si ningun valor se ha repetido mas de una vez no hay
141
moda
142     return -1;

143   } else {


144     for(int i=0; i<fils;i++){
145       for(int j=0;j<cols;j++){
146         if(maux.matr1[i][j] == mayor_) {
147           moda_ = matr1[i][j];
148         }
149       }
150     }

151   }
152   return moda_;
153 }
154  
155 //Intercambiar dos filas en una matriz
156 template<typename T>
157 void Matriz<T>::inter_filas(int fil1, int fil2)
158 {

159   if(fil1 > fils || fil2 > fils){


160     cout << "Por favor, hasta cuando " << endl;
161   } else {
162     T temp;
163     fil1--;
164     fil2--;
165  
166     for(int i=0;i<cols;i++){
167       temp = matr1[fil1][i];
168       matr1[fil1][i] =  matr1[fil2][i];
169       matr1[fil2][i] = temp;
170     }
    cout << "Se intercambio la fila " << fil1 + 1 << " por la " << fil2
171
+ 1 << endl;
172     imprimir();
173   }
174 }

175  
176 //Intercambiar dos columnas en una matriz
177 template<typename T>
178 void Matriz<T>::inter_cols(int col1, int col2)
179 {
180   if(col1 > cols || col2 > cols){
181     cout << "Por favor, hasta cuando " << endl;
182   } else{
183     T temp;
184     col1--;
185     col2--;
186  
187     for(int i=0;i<fils;i++){
188       temp = matr1[i][col1];
189       matr1[i][col1] =  matr1[i][col2];
190       matr1[i][col2] = temp;

191     }
    cout << "Se intercambio la columna " << col1 + 1 << " por la " <<
192
col2 + 1 << endl;
193     imprimir();
194   }
195 }
196  
197 //Verificar si una matriz es simetrica
198 template<typename T>
199 bool Matriz<T>::esSimetrica()
200 {
201   if(fils!=cols) {
202     return false;
203   }
204  
205   for(int i=0;i<fils;i++){
206     for(int j=0;j<cols;j++){
207       if (matr1[i][j]!=matr1[j][i]){
208         return false;
209        }
210     }

211   }
212   return true;
213 }
214  
215 //Verificar si una matriz es identidad
216 template<typename T>
217 bool Matriz<T>::esIdentidad()
218 {
219   if(fils!=cols) {
220     return false;
221   }
222  
223   for(int i=0;i<fils;i++){
224     for(int j=0;j<cols;j++){
225       if (i == j) {
226         if (matr1[i][j] != 1)
227           return false;
228       } else {
229         if (matr1[i][j] != 0)
230           return false;
231       }
232     }

233   }
234   return true;
235 }
236  
237 //Multiplicar a una matriz por un escalar
238 template<typename T>
239 void Matriz<T>::multi_escalar(T escalar)
240 {

241   for(int i=0;i<fils;i++){


242     for(int j=0;j<cols;j++){
243       matr1[i][j] = matr1[i][j] * escalar;
244     }

245   }
  cout << "Se multiplico a la matriz por el escalar " << escalar <<
246
endl;
247   imprimir();
248 }

249  
250 //Obtener la transpuesta de una matriz
251 template<typename T>
252 void Matriz<T>::transpuesta()
253 {
254   Matriz matresult(cols,fils);
255   for(int i=0;i<cols;i++){
256     for(int j=0;j<fils;j++){
257       matresult.matr1[i][j]= matr1[j][i];
258     }

259   }
260   matresult.imprimir();
261 }
262  
263 //Suma de matrices con sobrecarga de operadores
264 template<typename T>
265 Matriz<T> Matriz<T>::operator+ (const Matriz &matr2)
266 {
267   Matriz matresult(fils,cols);
268   for (int i=0;i<fils;i++){
269     for (int j=0;j<cols;j++){
270       matresult.matr1[i][j] = matr1[i][j] + matr2.matr1[i][j];
271     }
272   }
273   return matresult;
274 }

275  
276 //Resta de matrices con sobrecarga de operadores
277 template<typename T>
278 Matriz<T> Matriz<T>::operator- (const Matriz &matr2)
279 {
280   Matriz matresult(fils,cols);
281   for (int i=0;i<fils;i++){
282     for (int j=0;j<cols;j++){
283       matresult.matr1[i][j] = matr1[i][j] - matr2.matr1[i][j];
284     }

285   }
286   return matresult;
287 }
288  
289 //Multiplicacion de matrices con sobrecarga de operadores
290 template<typename T>
291 Matriz<T> Matriz<T>::operator* (const Matriz &matr2)
292 {
293   Matriz matresult(fils,matr2.cols);
294   T total;

295   for (int i=0;i<fils;i++){


296     for (int j=0;j<matr2.cols;j++){
297       for(int k=0;k<cols;k++){
298           total += (matr1[i][k] * matr2.matr1[k][j]);
299           //para mostrar lo que pasa
          /*cout << "(" << matr1[i][k] << " * " << matr2.matr1[k][j]
300
<< ")";
301           if(k<cols-1){
302               cout << " + ";
303           } else {
              cout << " = " << total;//despues del ultimo muestro la
304
suma
305           }*/
306       }

307       //cout << endl;


308       matresult.matr1[i][j] = total;
309       total = 0;//para limpiar el total sumado arriba
310     }
311     cout << endl;
312   }
313   return matresult;
314 }

315  
316 template<typename T>
317 void Matriz<T>::eliminar()
318 {
319   for(int i=0;i<fils;i++){
320     delete[] matr1[i];

321   }
322   delete[] matr1;
323 }
324  
325 template<typename T>
326 Matriz<T>::~Matriz(){}

main.cpp

view source
print?
01 #include <iostream>
02 #include "Matriz.h"
03 #include "Matriz.cpp"
04  
05 using namespace std;
06  
07 int main()
08 {
09     srand(time(NULL));//para no generar los mismos numeros aleatorios
10     int fils,cols,fil1,col1,fil2,col2;

11  
12     cout << "Ingresa nro de filas " << endl;
13     cin >> fils;
14     cout << "Ingresa nro de columnas " << endl;
15     cin >> cols;
16     cout << endl;
17  
18     Matriz<int> a(fils,cols);
19     Matriz<int> b(fils,cols);
    Matriz<int> c(fils,cols);//matriz para almacenar el resultado de
20
las operaciones
21  
    a.llenar_aleatorio();//existe el metodo llenar_teclado() para otros
22
tipos
23     b.llenar_aleatorio();
24  
25     cout << "Operaciones con matrices " << endl;
26     cout << "Matriz A " << endl;
27     a.imprimir();
28  
29     cout << "Matriz B " << endl;
30     b.imprimir();

31  
32     cout << "Matriz A + B " << endl;
33     c = a + b;
34     c.imprimir();
35  
36     cout << "Matriz A - B " << endl;
37     c = a - b;
38     c.imprimir();
39  
40     cout << "Matriz A * B " << endl;
41     c = a * b;
42     c.imprimir();
43  
44     cout << "Operaciones basicas con la matriz A" << endl;
45     cout << "Matriz A " << endl;
46     a.imprimir();

47  
48     cout << "El mayor de la matriz es: " << a.mayor() << endl;
49     cout << "El menor de la matriz es: " << a.menor() << endl;
50     cout << "La moda de la matriz es: " << a.moda() << endl;
51     cout << (a.esSimetrica() ? "" : "No") << " Es simetrica." << endl;
52     cout << (a.esIdentidad() ? "" : "No") << " Es identidad." << endl;
53     cout << endl;
54  
55     cout << "Ingresa el escalar " << endl;
56     cin >>a.escalar;
57     a.multi_escalar(a.escalar);
58  
59     cout << "Intercambio: Ingresa dos filas del 1 al " << fils << endl;
60     cin >>fil1;

61     cin >>fil2;
62     a.inter_filas(fil1,fil2);
63  
    cout << "Intercambio: Ingresa dos columnas del 1 al " << cols <<
64
endl;
65     cin >>col1;
66     cin >>col2;
67     a.inter_cols(col1,col2);
68  
69     cout << "Transpuesta de A " << endl;
70     a.transpuesta();

71  
72     a.eliminar();
73     b.eliminar();
74     c.eliminar();
75  
76     return 0;
77 }

Particularmente, todos los ejercicios no son nada difíciles de resolver, pero yo me estanqué
en la moda y creo que fue el problema que me hizo pensar un rato.

Lo resolví, pero sinceramente no me siento bien con la solución. No me gustó porque tiene
una complejidad de O(n2) y con una matriz muy grande puede tarda mucho debido al
número de recorridos y comparaciones.

La solución consistió en:

 Crear otra matriz auxiliar con el mismo nro de filas columas y llenarla con ceros.
 Recorrer la matriz original e ir comparando el primer elemento con todos los otros
elementos de la matriz y contar sus repeticiones y así sucesivamente con los demás
elementos.
 Si encuentro una repetición, incremento en uno el valor en esa posición de la matriz
auxiliar.
 Luego hallar el mayor elemento de la matriz auxiliar.
 Y finalmente recorrer la matriz auxiliar, cuando algún elemento de esta matriz sea
igual al mayor elemento, quiere decir, que ese fue el elemento que más se repitió en
la matriz original. Por lo tanto la moda se encuentra en esa posición.

view source
print?
01 Matriz original
02 17 16 10 26
03 10  3 9 19
04 29 7  1 6
05 6  20 0 10
06  
07 Matriz auxiliar al inicio
08 0 0 0 0
09 0 0 0 0
10 0 0 0 0
11 0 0 0 0
12  
13 Matriz auxiliar despues de las comparaciones
14 con el nro de repeticiones de los valores
15 1 1 3 1
16 3 1 1 1
17 1 1 1 2
18 2 1 1 3

La moda de la matriz es: 10,


3 es el valor maximo que se repite en la matriz
Y en las posiciones en que se encuentra 3 se encuentra 10 en la matriz original.

Un tip que me dió el profe es reducir el nro de comparaciones creando una matriz booleana
e ir poniendo unos y ceros a los números que ya comparé para luego no volver a comparar
con los números que comparé anteriormente. Voy a seguir resolviendo el problema,si
alguien tiene otra solución y puede explicarla fantástico.

You might also like