Documentos de Académico
Documentos de Profesional
Documentos de Cultura
TDA Arrayu Generico
TDA Arrayu Generico
ESTRUCTURAS DE DATOS
OBJETIVOS
Reconocer la utilidad de un tipo de dato Generico Utilizar TDAs ya creados para resolver problemas
INTRODUCCION
Enteros, reales, caracteres, lgicos Cuando se desea sumar dos enteros No es necesario conocer la representacin binaria de cada valor entero Solo debe conocerse el comportamiento que hace la suma: (+)
Qu ES UN ARREGLO?
El arreglo es un tipo de dato compuesto Permite agrupar elementos del mismo tipo Permite acceder a CADA elementos utilizando su posicin, recordemos que se puede
Consultar el valor de un elemento Modificar el valor de un elemento
ARREGLOS EN C
LOS PROBLEMAS
Si es un arreglo esttico,
El tamao real debe ser determinado desde el inicio, lo cual es muy molestoso
Si es un arreglo dinmico
El uso de malloc para crearlo abarca una cierta complejidad que podriamos ocultar
Puedo intentar asignar valores a elementos fuera del rango del arreglo Los ndices siempre comienzan desde 0 y eso no se puede cambiar El tamao del arreglo no es parte del arreglo etc. Que aaden complejidad al manejo de arreglos Recordemos la abstraccin: quitar complejidad, dejar solo lo necesario
ArrayU: COMPORTAMIENTO
Bsico: sin el cual no se puede trabajar con el TDA Complementario: operaciones que facilitan el manejo del TDA
Crearlo, de cualquier tamao Destruirlo Asignar un valor a uno de sus elementos Consultar el valor de uno de sus elementos Consultar el tamao mximo del arreglo Ordenarlo Buscar un elemento dado su valor, etc.
Comportamiento complementario
ArrayU: ESTADO
El ndice del primer elemento puede comenzar desde un numero dado El ndice del ultimo elemento seria igual a: indice_primero + tamao -1
::= {<elemento><inicial>, ... , <elemento><iterador>, <elemento><final>}
<arreglo>
<inicial>
<final> <nreal>
::= <entero_positivo>
::= <inicial>+<nreal>-1 ::= <digito>{<digito>}
Podemos pasar al nivel de implementacin Usando un lenguaje de programacin determinado Estndar para nombrar TDAs y operaciones
Es preferible crear un estndar til para todos los TDAs que se vayan a crear Ejemplo: <nombre_TDA>_<nombre_funcion> o <nombre_funcion><nombre_TDA>
MODULARIZACION DE ARCHIVOS
En la programacin estructurada, los TDAs se implementan en mdulos Un modulo normalmente esta compuesto por:
Contienen la declaracin del nuevo tipo y Los prototipos de las operaciones que estarn disponibles
Crear
Dado un tamao, ArrayU almacenara una arreglo de dicho tamao ArrayU *ArrayU_Crear (int tamanio, int inicial);
Eliminar
Dado un arreglo, se eliminara de memoria void ArrayU_Eliminar(ArrayU **A);
Consultar
int ArrayU_ GetElemento(ArrayU *A, int indice); Int ArrayU_GetTam(ArrayU *A); int ArrayU_GetInicial(ArrayU *A); Int ArrayU_GetFinal(ArrayU *A);
Consideraciones
Declaracin:
OJO: ArrayU solo servir para arreglos de enteros
Podemos usarlo en un programa Pedir n elementos por teclado, almacenarlos en un arreglo y luego mostrar la mitad de cada valor ingresado Usemos nuestra propia abstraccin
Lo implementamos solo para enteros Crear un TDA para cada tipo de dato
ArrayUI, solo para enteros, ArrayUF, para reales ArrayUS, para strings, etc.
Modificar ArrayU para que sea un arreglo de cualquier tipo de dato un arreglo de genericos
De que tipo son esos elementos? Si lo definimos de un tipo especifico, nuestro TDA quedar muy limitado Abstraernos y crear un Tipo de Dato Generico Este nuevo TDA permitir representar cualquier tipo de dato, sea un entero, un real, u otro TDA
Qu podemos hacer?
La idea es lograr almacenar cualquier tipo de dato dentro de una variable de tipo Generico
Una variable de tipo generico se puede crear
g 4
g 6
Pero al hacerlo, habr que especificar memoria para que tipo de dato exactamente Esto depender del tipo del valor que va a almacenar
g Mama
g
Papa
Generico g; g = CrearEntero(4);
Eliminar una variable de tipo Generico Modificar el valor escondido, Ej. Con enteros
Qu representa el Generico?
Es decir
No debe ser de ningn tipo al ser declarado Y dependiendo de quien lo use, En algn momento se convertira al tipo deseado Reserva de memoria dinmica y Conversin explicita de un tipo a otro
Esto implicara
En lenguaje C
Entonces
Operaciones
Creacin
Generico Generico_CrearEntero(int valor); Generico_Eliminar(Generico g); void Generico_AsignarEntero(Generico g, int valor); int Generico_ObtenerEntero(Generico g);
Eliminar
Modificar y Consultar
Declaracin
GENERICO: EN C
1007
72 5 Generico g; g = Generico_CrearInt(5); G Generico_SetInt(g,Generico_GetInt(g)+67); 2056 printf(%d\n, Generico_GetInt(g)); Mama y Papa Mama Generico_Eliminar(g); g = Generico_CrearString(Mama); 1343 strcpy(cad,Generico_GetString(g)); strcat(cad, y Papa); Mama y Papa Mama Generico_SetString(g, cad); printf(%d\n, Generico_GetString(g)); Generico_Eliminar(g);
Bien utilizado
El tipo de dato Generico puede ser sumamente til A lo largo de todo el curso Nunca olvidar que las conversiones sern necesarias Si las dejamos a un lado, el resultado ser no esperado ni deseado
REDEFINICION DE ARRAYU
Pedir n elementos por teclado, almacenarlos en un arreglo y luego mostrar la mitad de cada valor ingresado
main(){ ArrayU *Datos; int n, valor; Generico g; printf(Cuntos datos maximo desea ingresar?); n = GetInteger(); Datos = ArrayU_Crear(n,1); for(i = ArrayU_GetInicio(Datos); i <=ArrayU_GetFinal(Datos);i++){ //Inicio i en el for desde 1, no desde 0 printf(Ingrese el dato No., i); valor = GetInteger(); g = Generico_CrearEntero(valor); ArrayU_SetElemento(Datos,i, g); //Pido el elemento i } for(i = 1; i <= Datos.n ; i++){ g = ArrayU_GetElemento(Datos,i); valor= Generico_GetEntero(g)/2; Generico_SetEntero(g, valor); printf(Mitad del elemento %d: , Generico_GetEntero(g)); } ArrayU_Eliminar(&Datos); }
VENTAJAS Y DESVENTAJAS
Ventajas
Siempre tiene consigo su tamao, su ndice inicial y Sirve para cualquier tipo de dato
Desventajas
Como estamos muy acostumbrados al arreglo normal Este parece poco necesario
LO QUE DESEAMOS
Necesitara el arreglo, para poder imprimirlo y Pero como sabra como imprimir cada elemento???
Cada elemento es Generico, ArrayU no conoce el tipo de dicho Generico, y por lo tanto, no puede imprimirlo Un ArrayU, que es el que se desea imprimir Y algo que le indique como imprimir cada elemento del arreglo Pues desde dentro del TDA se desconoce como hacerlo
Que la funcin reciba una enumeracion que indique de que tipo es el ArrayU
void ArrayU_Imprimir(ArrayU *A, TipoDato tipo); En ese caso, la funcin debera elegir como imprimir el arreglo, dependiendo del tipo:
void ArrayU_Imprimir(ArrayU *A, TipoDato tipo){ for(i = 0; i< A->tmax; i++){ switch(tipo){ int *valor_int; char *cadena; Estudiante *E; Quebrado *Q; case ENTERO: valor_int = A>Elementos[i]; printf(%d\n, *valor_int); break; case CADENA: cadena = A>Elementos[i]; printf(%s\n, cadena); break; case ESTUDIANTE: E = A->Elementos[i]; Estudiante_Imprimir(E); break; case QUEBRADO: Q = A->Elementos[i]; Quebrado_Imprimir(Q);
DESVENTAJAS
Son obvias:
Esta funcin no sirve para cualquier tipo de dato Para que ArrayU soporte un nuevo tipo de dato hay que modificar la funcin
Buscar al creador del TDA Pedirle que aada un case para el nuevo tipo de dato Pedirle que recompile la librera Pedirle el nuevo .h y el nuevo .lib
MUCHO TRABAJO!!
SEGUNDA SOLUCIN
void ArrayU_Imprimir(ArrayU *A, procfn Imprimir){ for(i = 0; i< A->tmax; i++){ //Imprimir A->Elementos[i], NO SE COMO HACERLO //Llamo a la funcion Imprimir recibida como parametro Imprimir(A->Elementos[i]); }
} void void void void ImprimirEntero(int *valor); ImprimirCadena(char *cadena); Estudiante_Imprimir(Estudiante *E); Quebrado_Imprimir(Quebrado *Q);
main(){
ArrayU *A; A = ArrayU_Crear(10); //Se piden 10 Estudiante por teclado //y se almacenan en A ArrayU_Imprimir(A, Estudiante_Imprimir);
}
FUNCIONES CALLBACKS
Es una herramientas de programacin que nos ofrece lenguaje C Permite crear un tipo de dato que describa una funcin
En forma muy genrica Se indica tipo de dato de retorno Se indica los tipos de datos de entrada Ejemplo:
EJEMPLO: LA GRAPHAPP
Recibe un texto, un rectngulo y al parecer una variable de tipo actionfn Actionfn debe ser un nuevo tipo de dato, su declaracin es:
typedef void (*actionfn)(button b); Esto indica que cualquier funcin que coincida con el prototipo declarado para actionfn ser de tipo actionfn
Ejemplo:
void CalcularSalarios(button b); //. button b; b = newbutton(Aceptar, rect(10,10,10,10), CalcularSalarios);
SU UTILIDAD
Crear funciones que necesiten llamar a otras funciones La funcin callback que necesitamos cumplir la tarea de imprimir un dato Generico:
Cualquier funcin que tenga este prototipo caer en este tipo. Ejemplo:
LLAMANDO A LA IMPRESION
void Imprimir_Entero(int *valor); main(){ ArrayU *Datos; int n, valor; Generico g; printf(Cuntos datos maximo desea ingresar?); n = GetInteger(); Datos = ArrayU_Crear(n,1); for(i = ArrayU_Inicio(Datos); i <= ArrayU_Final(Datos) ;i++){ printf(Ingrese el dato No., i); valor = GetInteger(); g = Generico_CrearInt(valor/2); ArrayU_SetElementos(Datos,i,g); } ArrayU_Imprimir(Datos, Imprimir_Entero); ArrayU_Eliminar(&Datos); } void Imprimir_Entero(int *valor){ printf(%d, *valor); }