Especificacin de TADs. TAD Pila de Enteros. Definicin: Estructura de Datos que contiene una serie de elementos de tipo entero a los que s s lo lo se puede acceder por un nico lado. Caracterstica: Primer elemento obtenido es el ltimo introducido Estructura LIFO (Last input, First Output) Operaciones: apilar. desapilar. pilaVaca. inicializarPila. desapilar apilar Cima de la Pila 5 3 7 2 Cima de la Pila TAD Pila de Enteros: especificacin (I) Operacin Especificacin semntica Especificacin sintctica inicializarPila Mtodo que deja a disposicin del programa un TAD pila sobre el que se podr operar posteriormente. (Equivalente a crear o construir un objeto/instancia.). void inicializarPila () apilar * Mtodo que entrega un elemento (x) para que quede incorporado en la cima de la pila. void apilar (int x) desapilar * Mtodo que elimina el elemento que ocupa la cima de la pila y devuelve como resultado dicho elemento. int desapilar () pilaVacia Mtodo que al ejecutarse devuelve true si la pila est vaca (no tiene elementos), y false en caso contrario. boolean pilaVacia () cima * Mtodo que devuelve la cima de la pila (sin alterarla). int cima () decapitar * Mtodo que elimina el elemento de la cima de la pila. void decapitar () Especificacin de TADs. TAD Pila de Enteros (II) Operacin Especificacin semntica Especificacin sintctica leerPila Mtodo que se utiliza para realizar la carga inicial de elementos de la pila. void leerPila () throws NumberFormatException, IOException imprimirPila Mtodo que muestra en la pantalla el contenido de la pila. void imprimirPila () eliminar Mtodo que recibe una pila (que puede tener elementos o no) y la devuelve vaca. void eliminarPila () numElemPila Mtodo que devuelve el nmero de elementos de la pila. int numElemPila () Excepciones (I) Excepcin: circunstancia que produce que una Operacin Vlida sobre un TAD no pueda ser efectuada. Ejemplos: apilar: Al intentar apilar un nuevo elemento en la pila, sta est llena. La operacin apilar no debe producir ningn efecto. desapilar, cima, decapitar: Al intentar desapilar un elemento de la pila, obtener su cima o decapitarla, sta est vaca. Estas operaciones no deben producir ningn efecto Excepciones (II) Para Especificar completa y correctamente cada operacin vlida de un TAD se debe indicar: Especificaciones Sintcticas. Especificaciones Semnticas. Excepciones: Se indicarn como parte de las especificaciones semnticas. Interfaz del TAD Pila Define los mtodos de objeto utilizados en la clase TAD_PILA import java.io.*; public interface Pila { void inicializarPila (); boolean pilaVacia (); void eliminarPila (); int cima (); void apilar (int x); int desapilar (); void decapitar (); void imprimirPila (); void leerPila () throws NumberFormatException, IOException; int numElemPila (); } Prueba (condiciones normales) import java.io.*; public class pruebaPila1 { public static void main (String [] args) { Pila p = new TadPila (); int x; p.inicializarPila (); p.apilar (1); p.apilar (2); p.apilar (3); p.apilar (11); p.apilar (15); x = p.desapilar(); System.out.println ("x = " + x); x = p.desapilar (); System.out.println ("x = " + x); p.eliminarPila (); } } Situaciones de excepcin public class pruebaPila2 { public static void main (String [] args) { Pila pila1 = new TadPila (); int i, j; pila1.inicializarPila (); for (I = 1; I < 10; i++) pila1.apilar (i); j = pila1.desapilar (); for (I = 1; I < 10; i++) j = pila1.desapilar (); pila1.eliminarPila (); } } Algoritmos bsicos con Pilas Tratamiento recursivo. Ventaja: legibilidad. Inconveniente: consumo de memoria Justificacin: Adecuacin de la estructura a la tcnica. Restricciones del enunciado. Mecnica: desapilar llamar apilar. Terminaciones: Pesimista: Llegar al final. Anticipada: No llamar ms. Ejemplos: Imprimir los elementos de una pila - Contar los elementos de una pila static void escribirPila (Pila pila) { int elem; if (! pila.pilaVacia ()) { elem = pila.desapilar (); System.out.println (elem); escribirPila (pila); pila.apilar (elem); } } static int contarPila (Pila pila) { int elem, resul; if (! pila.pilaVacia ()) { elem = pila.desapilar (); resul = 1 + contarPila (pila); pila.apilar (elem); } else resul = 0; return resul; } Obtener el duplicado de una pila static void copiarPila (Pila pilaO, Pila pilaD) { int elem; if (! pilaO.pilaVacia ()) { elem = pilaO.desapilar (); copiarPila (pilaO, pilaD); pilaO.apilar (elem); pilaD.apilar (elem); } } Ejercicio propuesto: duplicar invirtiendo el orden de los elementos en la pila copia. Invertir el contenido de una pila Argumentos: Pila de origen y pila de destino (ambos por referencia) Fase de ida: desapilamos en pila origen y apilamos en la pila destino Fase de vuelta: apilamos en pila origen (para restablecer la pila) Fase de transicin: no hacemos nada Condicin de parada: pila vaca (sin terminacin anticipada) 5 3 7 2 2 7 3 5 Estado inicial 5 3 7 2 7 2 if (! pilaO.pilaVacia ()) { elem = pilaO.desapilar (); pilaD.apilar (elem); invertirPila (pilaO, pilaD); 3 5 elem = 3 7 2 3 5 elem = 5 7 2 5 elem = 2 3 7 2 5 elem = 7 3 pilaO.apilar (elem); } 7 2 3 7 7 2 5 3 7 2 7 2 3 5 7 2 5 3 7 2 5 3 7 2 5 3 Sumergir un elemento Consideraciones: Fase de ida: desapilamos elemento Condicin de parada: pila.pilaVacia () (sin terminacin anticipada) Transicin: Apilamos el dato que queremos sumergir Fase de vuelta: restablecemos la pila, apilamos el elemento static void sumergir (Pila pila, int dato) { int elem; if (!pila.pilaVacia ()) { elem = pila.desapilar (); sumergir (pila, dato); pila.apilar (elem); } else pila.apilar (dato); } Sumergir un elemento Invertir los elementos de una pila static void invertir (Pila pila) { int elem; if (!pila.pilaVacia ()) { elem = pila.desapilar (); invertir (pila); sumergir (pila, elem); } } Terminacin anticipada Parar la ejecucin del programa antes de alcanzar la condicin de parada si se cumple determinada condicin No se realizan ms llamadas recursivas. Condicin de parada pesimista: pilaVacia. Ejemplo: buscar un valor. Condicin de parada pesimista: pilaVacia Terminacin anticipada: existe dato no se realizan ms llamadas recursivas Fase de ida: desapilar elemde pila y comparar con dato Si igual termino llamadas recursivas Si no llamada a funcion recursiva Fase de vuelta: apilar elemen pila Quitar el elemento del fondo public static int desfondar (Pila p) { int elem, dato; if (!p.pilaVacia ()) { elem = p.desapilar (); if (! p.pilaVacia ()) { dato = desfondar (p); p.apilar (elem); } else dato = elem; } else { System.out.println ("error, la pila est vaca"); dato = -9999; } return dato; } Buscar un valor static boolean esta (Pila pila, int dato) { int elem; boolean resul; if (!pila.pilaVacia ()) { elem = pila.desapilar (); if (elem == dato) resul = true; else resul = esta (pila,dato); pila.apilar (elem); } else resul = false; return resul; } Terminacin anticipada Terminacin pesimista Varias Pilas: Mezclar dos Pilas (AND). (I). Estrategia Entrada: Dos pilas ordenadas ascendentemente (pila1 y pila2) Salida: Pila ordenada ascendentemente (pila3) con los elementos de pila1y de pila2 sin repeticiones. Argumentos: pila1, pila2, pila3: clase Pila. elem1, elem2: enteros. (No pueden ser variables locales). apilar1, apilar2: lgicos. (Elemento pendiente de apilar). Fase de ida: Variables de control: pend1 y pend2 (lgicos): La pila (1 2) tiene algo pendiente de tratar. Condicin de terminacin: Alguna de la pilas no tiene elementos por tratar (!(pend1 && pend2) (!pend1 || !pend2). Tratamiento: desapilar segn proceda (utilizar apilar1|2). Comparar elementos de pila1 y pila2. Llamada recursiva con los valores oportunos de apilar1 y apilar2. Fase de transicin: apilar en pila1 o pila2 algn posible elemento pendiente. Fase de vuelta: apilar en pila1o pila2 segn el valor de apilar1|2. apilar en pila3 solo cuando se corresponda con una instancia de la fase de ida en la que elem1 = elem2 Varias Pilas: Mezclar dos Pilas (AND). (II). Argumentos apilar1 y apilar2 Segn lo que haya ocurrido en la instancia anterior: pendiente de apilar en pila1 en pila2 Se inicializan en la llamada externa al programa, ambas a false. pend1 y pend2: quedan elementos por tratar en pila1|2 si no estn vacas (!pila1|2.pilaVacia ())o que dan elementos por tratar (apilar1|apilar2) pend1 = (!pila1.pilaVacia () || apilar1) pend1|2 = (!pila2.pilaVacia () || apilar2) Varias Pilas: Mezclar dos Pilas (AND). (III). Modelo Varias Pilas: Mezclar dos Pilas (OR). (I). Estrategia Entrada: Dos pilas ordenadas ascendentemente (pila1 y pila2) Salida: Pila ordenada ascendentemente (pila3) con los elementos de pila1y de pila2 sin repeticiones. Argumentos: pila1, pila2, pila3: clase Pila. elem1, elem2: enteros. (No pueden ser variables locales). apilar1, apilar2: lgicos. (Elemento pendiente de apilar). Fase de ida: Variables de control: pend1 y pend2 (lgicos): La pila (1 2) tiene algo pendiente de tratar. Condicin de terminacin: Alguna de la pilas no tiene elementos por tratar (!(pend1 && pend2) (!pend1 || !pend2). Tratamiento: desapilar segn proceda (utilizar apilar1|2). Comparar elementos de pila1 y pila2. Llamada recursiva con los valores oportunos de apilar1 y apilar2. Fase de transicin: Copiar el resto de la pila no vaca en pila3 ( Llamada al mtodo copiarPila). Tratar algn posible elemento pendiente de pila1 o pila2. Fase de vuelta: apilar en pila3. apilar en pila1o pila2 segn el valor de apilar1|2. Varias Pilas: Mezclar dos Pilas (OR). (II). Argumentos apilar1 y apilar2 Segn lo que haya ocurrido en la instancia anterior: pendiente de apilar en pila1 en pila2 Se inicializan en la llamada externa al programa, ambas a false. pend1 y pend2: quedan elementos por tratar en pila1|2 si no estn vacas (!pila1|2.pilaVacia ()) o que dan elementos por tratar (apilar1|apilar2) pend1 = (!pila1.pilaVacia () || apilar1) pend1|2 = (!pila2.pilaVacia () || apilar2) Varias Pilas: Mezclar dos Pilas (OR). (III). Modelo elem1 = 1 elem2 = 2 if (elem1 < elem2) mezclarPila (pila1,pila2,pila3,false,true,1,2) [1] pila1.apilar (1); pila3.apilar (1); 7 5 1 2 6 4 7 5 6 4 Ambas pilas tienen elementos por tratar (pend1 && pend2) if (!apilar1) elem1 = pila1.desapilar (); if (!apilar2) elem2 = pila2.desapilar (); [1] If (!apilar1) elem1 = pila1.desapilar (); elem1 = 5 elem2 = 2 if (elem2 < elem1) mezclarPila (pila1,pila2,pila3,true, false,5,2); [2] pila2.apilar (2); pila3.apilar (2); Varias Pilas: Mezclar dos Pilas (OR). (IV). Simulacin (I) elem1 = 5 elem2 = 4 if (elem2<elem1) mezclarPila(pila1,pila2,pila3,true,false,true,5,4); [3] pila2.apilar (4); pila3.apilar (4); Ambas pilas tienen elementos por tratar (pend1 && pend2) [2] if (! apilar2) elem2 = pila2.desapilar (); elem1 = 5 elem2 = 6 if (elem1<elem2) mezclarPila (pila1,pila2,pila3,false,true,5,6); [4] pila1.apilar (5); pila3.apilar (5); [3] if (! apilar2) elem2 = pila2.desapilar (); 7 6 4 7 6 Varias Pilas: Mezclar dos Pilas (OR). (IV). Simulacin (II) Ambas pilas tienen elementos por tratar (aux1 && aux2) elem1 = 7 elem2 = 6 if (elem2 < elem1) mezclarPila (pila1,pila2,pila3,true,false,7,6); [5] pila2.apilar (6); pila3.apilar (6); [4] if (!apilar1) elem1 = pila1.desapilar (); 7 [5] pend1; ! pend2; apilar1 if (apilar1) pila1.apilar (elem1); pila3.apilar (elem1); FASE DE VUELTA 7 7 Varias Pilas: Mezclar dos Pilas (OR). (IV). Simulacin (III) 7 7 6 6 4 2 1 5 5 4 2 1 [5] pila2.apilar (6); pila3.apilar (6); [4] pila1.apilar (5); pila3.apilar (5); [3] pila2.apilar (4); pila3.apilar (4); [2] pila2.apilar (2); pila3.apilar (2); [1] pila1.apilar (1); pila3.apilar (1); Varias Pilas: Mezclar dos Pilas (OR). (IV). Simulacin (IV) Varias pilas. Terminacin anticipada (I). Ejemplo. Mtodo que devuelve un valor lgico que indica si una pila de enteros ordenados ascendentemente desde la cima hacia el fondo (pila2) est contenida en otra (pila1) de las mismas caractersticas. Es una variante del algoritmo de mezcla AND con terminacin anticipada si durante la fase ida aparece un elemento de pila2 que no est en pila1 (elem2 < elem1). Fase de ida: Variables de control: pend1 y pend2 (lgicos): La pila (1 2) tiene algo pendiente de tratar. Condicin de terminacin (pesimista): Alguna de la pilas no tiene elementos por tratar (!(pend1 && pend2) (!pend1 || !pend2). Tratamiento: desapilar segn proceda (utilizar apilar1|2). Comparar elementos de pila1 y pila2. Si elem1 elem2, llamada recursiva con los valores oportunos de apilar1 y apilar2. En otro caso (Terminacin anticipada). No hay ms llamadas. Varias pilas. Terminacin anticipada (II). Fase de transicin: Por terminacin anticipada: Se apilan los elementos pendientes en pila1 y pila2 Se devuelve false. Por terminacin pesimista. Posibilidades: Se ha terminado con pila2 (y no con pila1). Se apila el elemento pendiente de pila1 Se devuelve true. Se ha terminado con pila1 (y no con pila2). Se apila el elemento pendiente de pila2 Se devuelve false. Se ha terminado con ambas pilas. Se devuelve true. Fase de vuelta: apilar en pila1o pila2 segn el valor de apilar1|2. Se devuelve el resultado a la instancia de llamada. En resumen. A la hora de manipular un TAD Qu tipo de problema? Crear un TAD a partir de otro, modificar el contenido, realizar clculos con los elementos del TAD Parmetros: TAD por referencia. Otros argumentos: por referencia o por valor?. Cules estn implcitos en el enunciado y cules no pero son necesarios Requieren inicializacin? Dnde los inicializo (fuera del mdulo recursivo, o dentro)? Condicin de parada Finalizacin anticipada: circunstancia que la provoca Diseo: Fase de ida: desapilar (+ operaciones) Transicin: se alcanza la condicin de parada y se realiza el proceso correspondiente Fase de vuelta: (Operaciones +) apilar Recapitulamos. Especificacin de un TAD: Propiedades sintcticas, propiedades semnticas y excepciones TAD Pila Estructura LIFO (Last Input First Output) Recursividad Fase de ida fase de transicin fase de vuelta Desapilar Procesar Apilar