Operaciones Con Matrices

22
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.

Transcript of Operaciones Con Matrices

Page 1: Operaciones Con Matrices

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.

Page 2: Operaciones Con Matrices

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 sourceprint ? 01 #ifndef MATRIZ_H02 #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();

Page 3: Operaciones Con Matrices

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 sourceprint ? 001 #include "Matriz.h"

Page 4: Operaciones Con Matrices

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));

Page 5: Operaciones Con Matrices

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++){

Page 6: Operaciones Con Matrices

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     }

Page 7: Operaciones Con Matrices

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 veces119   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]){

126           maux.matr1[i][j]++;//incremento en 1 el valor de la matriz aux en esa posicion

127         }

128       }

129     }

130     //pasar a la siguiente columna despues de n comparaciones

Page 8: Operaciones Con Matrices

131     z++;

132     if(z==cols){//empiezo a comparar con la siguiente fila133       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 matriz139   mayor_ = maux.mayor();

140  

141   if(mayor_==1){//si ningun valor se ha repetido mas de una vez no hay 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;

Page 9: Operaciones Con Matrices

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     }

171     cout << "Se intercambio la fila " << fil1 + 1 << " por la " << fil2 + 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     }

192     cout << "Se intercambio la columna " << col1 + 1 << " por la " << col2 + 1 << endl;

193     imprimir();

194   }

195 }

Page 10: Operaciones Con Matrices

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;

Page 11: Operaciones Con Matrices

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   }

246   cout << "Se multiplico a la matriz por el escalar " << escalar << 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     }

Page 12: Operaciones Con Matrices

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)

Page 13: Operaciones Con Matrices

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

300           /*cout << "(" << matr1[i][k] << " * " << matr2.matr1[k][j] << ")";

301           if(k<cols-1){

302               cout << " + ";

303           } else {

304               cout << " = " << total;//despues del ultimo muestro la 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;

Page 14: Operaciones Con Matrices

323 }

324  

325 template<typename T>

326 Matriz<T>::~Matriz(){}

main.cpp

view sourceprint ? 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);

20     Matriz<int> c(fils,cols);//matriz para almacenar el resultado de las operaciones

21  

22     a.llenar_aleatorio();//existe el metodo llenar_teclado() para otros tipos

23     b.llenar_aleatorio();

24  

25     cout << "Operaciones con matrices " << endl;

Page 15: Operaciones Con Matrices

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  

Page 16: Operaciones Con Matrices

59     cout << "Intercambio: Ingresa dos filas del 1 al " << fils << endl;

60     cin >>fil1;

61     cin >>fil2;

62     a.inter_filas(fil1,fil2);

63  

64     cout << "Intercambio: Ingresa dos columnas del 1 al " << cols << 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.

Page 17: Operaciones Con Matrices

view sourceprint ? 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 010 0 0 0 011 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 116 3 1 1 117 1 1 1 218 2 1 1 3

La moda de la matriz es: 10,3 es el valor maximo que se repite en la matrizY 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.