Elección de estructuras Algoritmos y Estructuras de Datos 2 Departamento de Computación, Facultad de Ciencias Exactas y Naturales, Universidad de Buenos Aires 10 de octubre de 2014
Repaso: Qué es elegir estructuras de datos? En el etapa de diseño: Nos ocupamos del cómo? Lo plasmamos en módulos de abstracción Ese cómo? se implementa usando el paradigma imperativo. Los módulos de abstracción tienen Servicios exportados e interfaz (público) Estructura de representación, Rep, Abs, algoritmos (privado) Justif. de complejidades (esto también es privado) ( por qué?) Servicios usados (esto también es privado) ( por qué?)
Qué es elegir estructuras de datos? Interfaz pública Ya lo vimos Estructura de representación y algoritmos Elegir un buen combo para cumplir los requerimientos (en este caso: de complejidad temporal) Servicios usados Tenemos que dejarles requisitos cumplibles (en este caso: justificamos dicha cumplibilidad)
Qué vamos a hacer hoy? Pensar un ejercicio grande completo. Atacar otras variantes del ejercicio para ver algunos trucos o familias de trucos útiles. Los ejercicios de las guías y parciales son más focalizados, requieren sólo uno o dos trucos. El TP requiere varias cosas, pero se puede y debe modularizar y hay que resolver todos los módulos (salvo los del apunte de módulos básicos).
Qué insumos tenemos? Apunte de diseño (para saber qué y cómo escribir) Estructuras vistas en la teórica (módulos incompletos) Apunte de módulos básicos (módulos completos) Algunos trucos de experiencia en programación. Hoy esperamos agregar varios a nuestra mochila de elección de estructuras. Próximamente tendremos también algoritmos de ordenamiento y de dividir y conquistar.
El problema Tenemos que diseñar un conjunto de personas. Persona Nombre (string, único) DNI (entero, único) Día de Nacimiento (entero, 1 a 365, no hay bisiestos) Año de Nacimiento (entero, 1 a M) M lo recibimos al comenzar el programa. Además recibimos la fecha actual para poder hacer consultas sobre la edad. Y el TAD? La especificación es clara y simple. ( ponéle...!?) Pero sobre todo, no es el objetivo de la clase.
Las operaciones que nos piden Obtener una lista con todas las personas del conjunto. Dado un nombre de persona, encontrar todos sus datos. Dado el DNI de una persona, encontrar todos sus datos. Dado el DNI de una persona, dar su edad actual en cantidad de años enteros. Dada una cantidad de años, decir cuantas personas tienen exactamente esa cantidad en este momento. Decir cuantas personas estan en edad jubilatoria (es decir, tienen al menos 65 años cumplidos). Agregar una persona nueva. Dado un nombre, borrar a la persona que tiene ese nombre.
Los requerimientos de complejidad temporal n es la cantidad de personas en el sistema l es la longitud del nombre recibido cómo parámetro Obtener una lista con todas las personas del conjunto O(1). Dado nombre, encontrar sus datos O(l). Dado DNI, encontrar sus datos O(log n). Dado DNI, dar su edad actual O(log n). Dada una cantidad de años, decir cuantas personas tienen esa cantidad O(1). Decir mayores de 64 O(1). Agregar una persona nueva O(l + log n). Dado un nombre, borrar a la persona O(l + log n).
El comienzo persona es tupla nombre: string, dni: nat, día: nat, año: nat base se representa con estr, donde estr es tupla todos: lista(persona),...,...
Más operaciones y requerimientos Consultar la fecha actual O(1). Pasar de día O(m) m: cantidad de personas que cumplen años en el día al que se llega luego de pasar. Qué agregamos? Qué hace falta para mantenerlo?
Adicionales Dada una cadena, cantidad de personas cuyo nombre empieza con ella O(l). Iterar las cantidades de años en que al menos una persona tiene esa edad O(M) Iterar las cantidades de años en que al menos una persona tiene esa edad O(x) Dado un DNI, cuantas personas hay con DNI mayor o igual O(log n). x: cantidad de años tales que alguna persona tiene esos años Qué agregamos? Qué hace falta para mantenerlo?
Observaciones importantes Tener muy en cuenta los invariantes... de nuestra estructura, para no olvidarnos de mantenerlos.... de estructuras conocidas, para poder aprovecharlas. Tener punteros/iteradores/referencias cruzadas puede servirnos para mejorar el orden de complejidad. Pero cuidado: no podemos tener punteros a cosas de la estructura de representación de otro módulo que no deberíamos conocer. ( No romper el encapsulamiento!)
Recomendaciones Es conveniente tener claro para qué sirve cada parte de nuestra estructura y estar convencidos de que la estructura funciona antes de pensar los detalles más finos (de sentarse a escribir los detalles de Rep, Abs, algoritmos, etc). Sugerencia: esbozar los algoritmos en recontra-pseudo-código (a muuuuy alto nivel, por ejemplo en una servilleta!), y ver que las cosas más o menos cierren. Si algo no cierra, arreglarlo. El diseño es un proceso iterativo, y suele involucrar algunas vueltas de prueba y error. No desalentarse si las cosas no cierran de entrada. Persevera y triunfarás.
Gracias por su atención Preguntas...?