ESTRUCTURA DE DATOS Y ALGORITMOS Titulación: Ingeniero Técnico en Informática de Gestión Curso: 2º Nombre y apellidos: Nota:

Documentos relacionados
Agradecimientos. Nota de los autores. 1 Problemas, algoritmos y programas 1

Clase adicional 9. Listas enlazadas. Temas. Listas enlazadas Árboles Problemas de la clase adicional Ejercicios de diseño

Tema 2 Tipos abstractos de datos. 2.2 Pila de números enteros

Titulación: Ingeniero Técnico en Informática de Gestión Curso: 2º

Estructura de Datos. Árboles Binarios de Búsqueda ABB. Primer Semestre, 2010

Tema 8- Implementación de Pila, Cola y. Tema 8- Implementación de Pila, Cola y Lista con Punto de Interés. Representación Eficaz de una EDA

Tema 9. Algoritmos sobre listas. Programación Programación - Tema 9: Algoritmos sobre listas

Tema 3. Análisis de costes

Programación de sistemas Pilas y Colas

1. Leer el primer número y almacenarlo en la raíz del árbol. 2. Repetir hasta encontrar un duplicado o el árbol esté vacío.

TAD: Pila. TALLER: TAD Pila

11. PILAS Introducción Fundamentos

Clase 26. Introducción a los árboles. Árboles

PILAS Fundamentos

Unidad II: Análisis semántico

APUNTADORES. Un apuntador es un objeto que apunta a otro objeto. Es decir, una variable cuyo valor es la dirección de memoria de otra variable.

Estructuras de Datos y de la Información Ingeniería Técnica en Informática de Gestión. Curso 2007/2008 Ejercicios del Tema 2

Universidad de Valladolid. Departamento de informática. Campus de Segovia. Estructura de datos Tema 4: Ordenación. Prof. Montserrat Serrano Montero

Construcciones del Lenguaje Java

Algorítmica y Complejidad. Tema 3 Ordenación.

Unidad Didáctica 2. Elementos básicos del lenguaje Java Tipos, declaraciones, expresiones y asignaciones

Árboles binarios de búsqueda

LA ESTRUCTURA DE DATOS PILA EN JAVA. CLASE STACK DEL API JAVA. EJEMPLO Y EJERCICIOS RESUELTOS. (CU00923C)

Mostrar Números Ascendentemente. Soluciones Ejercicios Tema 5. tostring Recursivo de LEG. Suma Recursiva de un Vector (1/3)

TAD CONJUNTOS Y MULTICONJUNTOS

El método main de la clase PruebaArbol, empieza creando una instancia de un objeto Árbol vacío y asigna su referencia a la variable árbol

Tema 6. Gestión dinámica de memoria

<tipo> Tipo de dato de los elementos del vector

Tema 5. Estructura de datos Pila

Estructura de datos Colas

Clases e instancias. Algoritmos y Estructuras de Datos I. Clases e instancias. memoria dinámica.

Tema 5 Tabla de Símbolos

ORDENAMIENTO Y BÚSQUEDA EN ARREGLOS

Algoritmos. Medios de expresión de un algoritmo. Diagrama de flujo

A l g o r i t m o y E s t r u c t u r a d e D a t o s Ing. en Sistemas de Información - 1º año -

NIVEL 15: ESTRUCTURAS RECURSIVAS BINARIAS

Estructuras de Datos. La pila es un objeto dinámico en constante cambio.

Programación. Tema 8: Tablas Hash. Apuntes elaborados por: Eduardo Quevedo, Aaron Asencio y Raquel López Revisado por: Javier Miranda el????

Alonso Ramírez Manzanares Computación y Algoritmos 10.03

Complejidad computacional (Análisis de Algoritmos)

Estructuras de Datos y Algoritmos TDA LISTA

Tema 7.- Fundamentos de la Programación Orientada a Objetos

Programación de sistemas

Concepto de Recursión. Características de algoritmos recursivos. Ejemplos

TEMA 7: Ficheros. TEMA 7: Ficheros Concepto de fichero

Solución al Examen de Prácticas de Programación (Ingeniería Informática)

Capitulo V Listas Enlazadas

Tablas de Dispersión (Hashing Tables)

Árboles balanceados (AVL) Tablas de dispersión (Hash) Colas de prioridad (Heap)

Estructuras de datos: Pilas, Colas, Listas

TIPO DE DATO ABSTRACTO (TDA)

Estructura de Datos. Unidad de Aprendizaje: Unidad de Competencia II: Estructuras de Datos Lineales. M. en C. Edith Cristina Herrera Luna

Ejercicios de Hilos. Índice

1. Cuántas sentencias hay en la secuencia principal del siguiente programa?

FUNDAMENTOS DE PROGRAMACIÓN. SEPTIEMBRE 2005

INTERFACE COMPARATOR. DIFERENCIAS ENTRE COMPARATOR Y COMPARABLE. CLASE COLLECTIONS. EJERCICIOS RESUELTOS. (CU00918C)

Introducción Supongamos un subconjunto de n elementos X = {e 1,,e n de un conjunto referencial Y, X Y. Dentro de Y se define una relación de orden tot

INDICE Capitulo 1. introducción a las computadoras y a la programación Capitulo 2. El lenguaje de programación Java. aplicaciones y programas

Tipos algebraicos y abstractos. Algoritmos y Estructuras de Datos I. Tipos algebraicos

Procesadores de lenguaje Tema 6 La tabla de símbolos

Notación Asintótica 2

Pauta control 2 CC10B

Estructuras de Datos Clase 1 - Introducción

Universidad de Guadalajara Centro universitario de los Altos Licenciatura en Ingeniería en Computación

4. Operadores Operador asignación

Carlos Montenegro. Programación Orientada a Objetos Proyecto Curricular de Ingeniería de Sistemas

La eficiencia de los programas

324 MR Versión 1 Prueba Integral 1/3 Semana 10 Lapso

Tabla de Símbolos. Programación II Margarita Álvarez

El TAD Grafo. El TAD Grafo

Unidad II. Fundamentos de programación en Java. Ing. José Luis Llamas Cárdenas

Tabla de Símbolos. Programación II Margarita Álvarez

Elementos léxicos del lenguaje de programación Java

3.3 Conceptos Básicos del Lenguaje Java

FUNDAMENTOS DE PROGRAMACIÓN Curso: 2013/14 EXAMEN PARA ALUMNOS PRESENTADOS AL PRIMER PARCIAL PRIMERA PARTE. EJERCICIO 1 Cuestiones (1 punto)

Clase 31. Hashing (Dispersión) Motivación

16 Análisis sintáctico I

Tema 2. El lenguaje JAVA

Introducción a la computación. Charlie

PROGRAMACION ORIENTADA A OBJETOS Ingenieria Informática Final Febrero 2006/07

Centro Asociado Palma de Mallorca. Antonio Rivero Cuesta

ESTIMACIÓN DE TIEMPO Y COSTO DE PRODUCTOS SOFTWARE

Tema 2. El lenguaje de programación Java (Parte 1)

UAA Sistemas Electrónicos Estructura de Datos Muñoz / Serna

Árboles Carlos Delgado Kloos Mª Carmen Fernández Panadero Raquel M. Crespo García Ingeniería Telemática Univ. Carlos III de Madrid

EXAMEN PROGRAMACIÓN 21 de Septiembre de 2007 INGENIERÍA INFORMÁTICA Primera parte: Cuestiones 1,5 horas

$0 Representa al parámetro cero o nombre del programa $1 Representa al parámetro uno $2 Representa al parámetro dos

Universidad Autónoma del Estado de México 2016, Año del 60 Aniversario de la Universidad Autónoma del Estado de México

Programación en Lenguaje C

Algoritmos de Ordenación

Prueba N o 1. Programación II

Arquitecturas cliente/servidor

Patrones de Diseño. Patrón estructural Composite. Técnicas de Programación - Curso 2007/08

Tema: Funciones, Procedimientos y Recursividad en C#.

Estructuras de datos: Árboles binarios de

SENA Distrito Capital Centro de Electricidad, Electrónica y Telecomunicaciones ADSI - Ing. Espec. Javier Vaquiro

ÁRBOLES PARCIALMENTE ORDENADOS

Ejercicios de Programación Tema 7. Programación Orientada a Objetos

PROGRAMACIÓN ORIENTADA A OBJETOS (L40629) Sabino Miranda-Jiménez

Tema 4 Colecciones en Java. Programación Orientada a Objetos Curso 2013/2014

Transcripción:

Nombre y apellidos: Nota: 1. Ejercicio (3 puntos) a) Qué estructura de datos utilizarías para transformar la siguiente expresión a su equivalente expresión postfija? Argumenta tu decisión. Ej. entrada: (x-y)/(z+w) (z+y)^x Salida: xy-zw+/zy+x^- Utilizaría una pila, porque se necesitan apilar los operadores según su precedencia o prioridad, para ello también habría que apilar los paréntesis de apertura. Los operadores se desapilarán cuando en la expresión de entrada se haya leído: 1) un operador que tiene menor o igual precedencia que el de la cima; o 2) un paréntesis de cierre, en ese caso se desapilan hasta el paréntesis de apertura. b) La solución de un problema concreto requiere la ejecución de las dos siguientes operaciones una y otra vez sobre un conjunto de datos: 1) buscar un dato por contenido y 2) insertar más datos después del dato encontrado en 1). Qué estructura de datos sería la más adecuada? Argumenta tu decisión. Una lista enlazada (independiente del tipo de lista) sería la más adecuada, porque al no utilizar una estructura estática en memoria para la representación de los datos, las operaciones comentadas no requieren desplazamiento de los datos anteriores y además hace un uso justo de la memoria requerida. También podría ser valido un árbol con los mismos argumentos. c) Cual es la complejidad del algoritmo de búsqueda de un elemento por posición en una lista? Es siempre igual? Argumenta tu respuesta. Se podría particularizar y decir que: para la lista vacía y primer y último elemento es O(1) y O(n) para otros casos. Pero hay que recordar que la complejidad de un algoritmo lo caracteriza el caso peor. En este caso la complejidad depende de la implementación de la lista. Si es enlazada, es decir, dinámica entonces es O(n) y si fuera estática, se utilizaría un array o vector, entonces sería O(1). d) En las TablasHash abiertas o hashing enlazado, la operación de insertar un elemento se ha realizado como primer elemento de la lista. Si la inserción en la lista enlazada se hace de tal forma que esté ordenada respecto a la clave. Qué ventajas y desventajas tiene respecto a la eficiencia de las operaciones insertar, buscar y eliminar? Esta estructura En el caso de insertar es una desventaja, ya que en la alternativa que se propone se requiere insertar ordenado en la posición correspondiente, lo cuál dependerá del número de colisiones (misma clave) que se produzcan (tamaño de la lista) y dejará de ser constante. En cuanto a buscar y eliminar, podemos decir que es ventaja en los casos en que la clave que se quiere buscar o eliminar no exista. Antes, siempre requería recorrer toda la lista y en cambio, con la nueva alternativa sólo se recorre hasta encontrarlo o encontrar una clave mayor o menor (dependiendo del criterio de ordenar) a la que se está buscando. e) Muestra que es posible soportar simultáneamente las operaciones siguientes en tiempo constante: apilar, desapilar, cima y buscarmin. Observa que eliminarmin no forma parte del repertorio. Pista: mantener dos pilas. 1. Explica que es lo que almacenarías en cada una de las pilas y la estrategia que sigues o el uso que haces de las dos pilas. En la pila1 apilaremos todos los datos, según se vayan apilando. La cima indica el último dato apilado, el cuál será el primero en desapilar. Así, los métodos apilar, desapilar y cima se ejecutarán en tiempo constante. En cambio, en la pila2 solamente apilaremos los datos que son mínimos según vayan apareciendo. La cima indica el valor mínimo actual. De está forma se garantiza que buscarmin se ejecute en tiempo constante. En está pila no tienen porque estar todos los datos. Apilaremos un dato en la pila2 cuando se de alguno de los siguientes casos: 1) el dato que apilamos es menor que el que está en la cima de la pila2; y 2) después de ejecutar desapilar o eliminarmin, el dato que está en la cima de la pila1 sea menor que el dato en la cima de la pila2.

2. representa el de las dos pilas, después de ejecutar aquellas instrucciones, que cambian el de las dos pilas (p.ej. apilar, desapilar y eliminarmin), del siguiente programa: programa 1) PilaCP p = new PilaCP(); 2) p. apilar(new Integer(6)); pila1 pila2 programa 3) p. apilar(new Integer(4)); 4) p. apilar(new Integer(7)); programa 5) p. apilar(new Integer(5)); 6) p. apilar(new Integer(3)); programa 7) p. cima(); programa 9) p.desapilar(); 8) p.buscarmin(); programa 10) p. cima(); programa 12) p.eliminarmin(); 11) p.buscarmin(); programa 13) p. cima(); programa 15) p.eliminarmin(); 14) p.buscarmin(); programa 16) p. cima(); programa 18) p.eliminarmin(); 17) p.buscarmin();

Nombre y apellidos: 2. Ejercicio (2 puntos) Se pide: a) (0,75 punto) Diseño El diseño principal sería utilizar dos estructuras de datos iguales (p.ej Vector, Array, VectorOrdenado o ArrayOrdenado) con la característica de que los datos se almacenan ordenados (p.ej de menor a mayor). Sería mejor algo de tipo Vector que Array, porque no se sabe el número de contactos. Además se almacenarían los mismos datos en las dos estructuras de datos, en una de ellas ordenados por el nombre del contacto y en la otra por teléfono. El uso del Vector y el ordenar sería principalmente para luego realizar una búsqueda eficiente, tal como, la búsqueda binaria. Las dos funcionalidades o características requieren que los datos a almacenar sean comparables, bien implementando la interfaz Comparable o Comparator. Principalmente, la dificultad reside en implementar las clases que van a representar los datos a almacenar. Tenemos dos opciones (con implementar una suficiente): 1) Utilizar la clase Contacto para representar los datos y dos clases para realizar las comparaciones, en una por nombre y en la otra por teléfono, implementando para ello la interfaz Comparator. 2) Una clase genérica (p.ej. ElementoAgenda), que represente los datos clave-valor e implemente la interfaz Comparable comparando la clave. Además de dos concretas (p.ej NombreContacto y TelefonoContacto) para realizar las correspondientes relaciones y recuperar datos. En las dos opciones, cualquier método relacionado con insertar, buscar o eliminar requiere ser genérica y parametrizada con la correspondiente interfaz. Un ejemplo de ello lo veremos en el apartado b) de este ejercicio. Falta figura Implementación public class Agenda { / * Por un lado almacenaremos los contactos ordenados por nombre. Dos opciones: * 1) se almacenan elementos de tipo Contacto ordenados según ContactosPorNombre * 2) se almacenan elementos de tipo NombreContacto ordenado por clave */ VectorOrdenado agendapornombre = new VectorOrdenado(); / * Por otro lado almacenaremos los contactos ordenados por teléfono. Dos opciones: * 1) se almacenan elementos de tipo Contacto ordenados según ContactosPorTelefono * 2) se almacenan elementos de tipo TelefonoContacto ordenado por clave */ VectorOrdenado agendaportelefono = new VectorOrdenado();

Dos posibles implementaciones de datos serían las siguientes (puede que haya más): 1) public class ContactosPorNombre implements Comparator { public int compare (Object obj1, Object obj2){ Contacto c1 = (Contacto) obj1; Contacto c2 = (Contacto) obj2; return c1.getnombre().compareto(c2.getnombre()); public class ContactosPorTelefono implements Comparator { public int compare (Object obj1, Object obj2){ Contacto c1 = (Contacto) obj1; Contacto c2 = (Contacto) obj2; return c1.gettelefono().compareto(c2. gettelefono()); 2) public class ElementoAgenda implements Comparable{ private String key; private ElementoAgenda valor; public int compareto(object obj){ if (obj instanceof ElementoAgenda) { ElementoAgenda elem = (ElementoAgenda) obj; return this.clave.equals(elem.clave); return false; public abstract String getnombre(); public abstract String gettelefono(); public class NombreContacto extends ElementoAgenda{ public NombreContacto(String nombre){ super(nombre); public ElementoAgenda settelefono(string telefono){ if (this.valor == null) this.valor = new TelefonoContacto(telefono); this.valor.clave = telefono; return this.valor; public String getnombre(){ return key; public String gettelefono(){ return valor.key; public class TelefonoContacto extends ElementoAgenda{ public TelefonoContacto (String telefono){ super(telefono); public ElementoAgenda setnombre(string nombre){ if (this.valor == null) this.valor = new NombreContacto (nombre); this.valor.clave = nombre; return this.valor; public String getnombre(){ return valor.key; public String gettelefono(){ return key;

b) (1 punto) Implementar los métodos buscartelefono y buscarnombre de la clase Agenda. Ten en cuenta que se ejecutan con mucha frecuencia y tu respuesta en el apartado anterior. 1) public String buscarnombre(string telefono){ Comparator portelefono = new ContactosPorTelefono(); Contacto buscar = new Contacto(null, telefono); Contacto contacto = (Contacto) buscarbinario(agendaportelefono, portelefono, buscar); if (contacto!= null) return contacto.getnombre(); return null; public String buscartelefono(string nombre){ Comparator pornombre = new ContactosPorNombre(); Contacto abuscar = new Contacto(nombre, null); Contacto contacto = (Contacto) buscarbinario(agendapornombre, pornombre, abuscar); if (contacto!= null) return contacto.gettelefono(); return null; public Object buscarbinario(vectorordenado v, Comparator comp, Object obj){ int central; int inicio = 0; int fin = a.length -1; while (inicio <= fin) { central = (inicio + fin) / 2; if(comp.compare(obj,v.elementat(central)) == 0) return v.elementat(central); if(comp.compare(obj, v.elementat(central)) > 0) inicio = central + 1; // (comp.compare(obj, v.elementat(central)) < 0) fin = central - 1; return null; c) (0,25 puntos) Calcula cual es la complejidad, en notación O, de los métodos implementados en b). Los dos métodos, buscartelefono y buscarnombre, dependen del método buscarbinario. Este método realiza una serie de comparaciones, que no es lineal, hasta encontrar el elemento buscado. Principalmente, tiene la característica que, al estar los datos de entrada ordenados, en cada iteración reduce el tamaño de los datos de entrada a la mitad que en el caso anterior (marcada por inicio y fin) n, n/2, n/4, n/8... esto es: n/2 i Ultima vuelta (caso peor) es cuando n/2 i =1 2 i =n Esto es cuando i=log 2 n Esto quiere decir que se darán log 2 n vueltas en el bucle (caso peor). Por lo tanto O(log 2 n) Nota: Se valorarán los aspectos de reutilización.

3. Ejercicio (1 punto) Se pide: a) Implementar las clases necesarias (sin los métodos) para representar una lista enlazada con doble terminación. class Node { Object element; Node next; public class DoubleEndedLinkedList{ Node top; Node bottom; public class DoubleEndedLinkedListItr { DoubleEndedLinkedList thelist; Node current; Node preceding; b) Implementar la heurística mover-al-frente para las listas enlazadas con doble terminación. public class DoubleEndedLinkedListItr { /* Este método mueve el nodo current al frente de la Lista. * PRE: Este método es principalmente invocado desde el método buscar, el cual * ha posicionado la variable current en el nodo que contiene el elemento * buscado. * POST: el nodo current pasa a ser el primero de la lista. */ private void moveralfrente(){ if (thelist.top!= current && current!=null) { if (thelist.bottom == current) thelist.bottom = preceding; // 0 preceding.next = current.next; // 1 current.next = thelist.top; // 2 thelist.top = current; // 3 preceding = null; // 4 c) Describir gráficamente los pasos principales de la heurística mover-al-frente, mediante un ejemplo. Falta figura

5. Ejercicio (3 puntos) 1. Especificación - Entrada: Un cuento dinámico y un entero, i, que representa la posición de un capitulo en un cuento normal. - Salida: un entero, que representa el número de capítulos que son afirmativos, están sin terminar y además, están en la posición i de los respectivos cuentos normales. public int numerodecapituloseniafirmativosysinterminar(int i) Analizando la situación, vemos que sería más fácil resolver el problema por recursividad. Para ello, necesitamos especificar mejor el problema añadiendo más parámetros como datos de entrada: 1) Necesitamos una forma de representar subcuentos dinámicos, para poder crear subproblemas. Para ello, utilizaremos la definición recursiva del árbol binario. 2) Necesitamos saber cual es la posición del primer capítulo del subcuento en el cuento original. 3) Necesitamos saber también si el primer capítulo del subcuento es afirmativo o no. Este dato lo indica el capitulo anterior del cuento original. Por lo tanto, añadimos 3 parámetros más al método y la especificación quedaría de la siguiente forma: - Entrada: A, un árbol binario que representa un cuento dinámico; un entero, i, que representa la posición de un capitulo en un cuento normal; un entero, pos, que indica la posición del primer capítulo de A en el esquema inicial de cuentos dinámicos y un booleano, esafirmativo, que indica si el primer capitulo de A es afirmativo o no. - Salida: un entero, que representa el número de capítulos que son afirmativos, están sin terminar y además, están en la posición i de los respectivos cuentos normales que empiezan en la raíz de A. private int numcapiafirmsinterminar(btnode A, int i, int pos, boolean esafirmativo) 2. Diseño a) casos triviales 1) Árbol vacío 0. 2) Árbol no vacío y i<pos 0. 3) Árbol no vacío, i=pos y no(esafirmativo) 0. 4) Árbol no vacío, i=pos, sinterminarprimercapitulo(a) y esafirmativo 1. b) casos generales 1) Árbol no vacío y i > pos numcapiafirmsinterminar(a.sigcapafirmativo, i, pos+1, true) + numcapiafirmsinterminar(a.sigcapnegativo, i, pos+1, false) Notas: 1) PrimerCapitulo(BTNode A) el capitulo que está en el nodo raíz de A 2) sinterminarprimercapitulo(btnode A) True si PrimerCapitulo(A) tiene pregunta y además, no existe alguno (o los dos) de los siguientes capítulos del PrimerCapitulo(A), es decir, alguna de las respuestas posibles a la pregunta están sin asociar a los capítulos correspondientes. 3) A.sigCapAfirmativo el nodo del árbol que contiene el siguiente capitulo, en caso de que se conteste afirmativamente a la pregunta del primer capitulo de A 4) A.sigCapNegativo el nodo del árbol que contiene el siguiente capitulo, en caso de que se conteste negativamente a la pregunta del primer capitulo de A

3. Implementación public class EsquemaCuentosDinamicos {... public int numerodecapituloseniafirmativosysinterminar(int i){ return itrcapitulos.numerodecapituloseniafirmativosysinterminar(i); public class CapitulosBinTreeItr {... public int numerodecapituloseniafirmativosysinterminar(int i){ return numcapiafirmsinterminar(btree.getroot(), i, 1, false); private int numcapiafirmsinterminar(btnode A, int i, int pos,boolean esafirmativo){ if ((A == null) (i<pos) ((i==pos) &&!esafirmativo)) ) return 0; if ((i==pos) && esafirmativo && sinterminarprimercapitulo(a)) return 1; return numcapiafirmsinterminar(a.getleft(), i, pos+1, true) + numcapiafirmsinterminar(a.getright(), i, pos+1, false); /* PRE: A no es vacio * POST: Devuelve True si el capitulo de la ráiz de A tiene pregunta y además, está * sin terminar. */ private boolean sinterminarprimercapitulo(btnode A){ Capitulo c = (Capitulo) A.getContent(); return ((c.tienepregunta()) && ((A.getLeft()==null) (A.getRight()==null)));