Upload
fiorella-pajares-alatrista
View
163
Download
2
Embed Size (px)
Citation preview
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 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();
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"
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 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
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;
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 }
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 }
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 }
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
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;
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;
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
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.
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.