Está en la página 1de 42

Pilas

Laboratorio de Programación II
Definición de pila
• Consideremos una pila de libros:
– Si añadimos un libro a la pila, los de
abajo son empujados y quedan
inaccesibles
– Si retiramos un libro de la pila, los
que están debajo ascienden una
posición
– La pila está vacía cuando no hay más
libros
– La pila está llena si no hay lugar para
más libros.
TAD pila
• Conjunto de elementos que sólo son accesibles
por un extremo, llamado el tope de la pila
• Operaciones básicas:
– Construcción (crear pila vacía)
– Vacía (comprobar si la pila está vacía)
– Apilar (agregar un nuevo elemento al tope de la pila)
– Tope (recuperar el elemento superior de la pila)
– Desapilar (eliminar el elemento superior de la pila)
Apilar y Desapilar (push – pop)
Diseño y construcción de la pila
Construcción
1) Diseño
2) Implementación
Diseño
• constructor (construye una pila vacía)
• vacía(): examinar la pila y devolver V o F
• apilar(): modificar la pila, agregando un valor
en el tope
• tope(): recupera el valor de la parte superior
de la pila
• desapilar(): modifica una pila eliminando el
valor en la cima.
Implementación
• Distinguimos dos pasos:
– definir los atributos para guardar los valores de la
pila
– definir los métodos identificados en la fase de
diseño.
Implementación 1
• Basada en un vector, con la posición 0 como el
tope de la pila.
0 77
1 121
2 64 Apilar Apilar
Desapilar
3 234 95 80
4 51 77 95 80 95
5 29 121 77 95 77
6 ?? 64 121 77 121
7 ?? 234 64 121 64
51 234 64 234
29 51 234 51
?? 29 51 29
?? ?? 29 ??
Un método mejor
• El desplazamiento de los elementos del vector
de la implementación anterior es innecesario.
• Pensemos en una pila de libros sobre una
mesa. ¿podemos añadir un libro sin tocar el
resto?
• Podemos “dar vuelta el vector”, fijando la
posición 0 en la base de la pila y el último
elemento en el tope. Asi no necesitaríamos
desplazar los elementos del vector.
Demos vuelta el vector
• Nuestra clase de pilas será:
– Un vector para guardar los elementos de la pila
– Un entero que señale el tope de la pila.
IMPLEMENTACIÓN DE
OPERACIONES
Constructor
• El compilador pide memoria para los atributos
miVector y miTope, con lo que el constructor
pila sólo necesita encargarse de la
inicialización necesaria para crear una pila
vacía.

• Como miTope siempre apunta al tope de la


pila, asignamos a miTope el valor -1 para
indicar que la pila está vacía.
Vacía
• comprobar que miTope es -1
Apilar
si (miVector NO está lleno)
(es decir miTope < CAPACIDAD_PILA -1)
Incrementar miTope en 1
Guardar el valor en miVector[miTope]
sino
señalar que no hay espacio disponible para el valor
terminar la operación.
Tope
si (la pila NO está vacía)
devolver el valor en miVector[miTope]
sino
señalar que la pila está vacía
devolver “valor basura”

Hay que definir cuál es el “valor basura” para


devolverlo en caso que la pila esté vacía.
Desapilar
si (la pila NO está vacía)
decrementar miTope en 1
sino
señalar que la pila está vacía
Implementación basada en vectores
dinámicos
• ¿Cuánto espacio hay que reservar para la pila?
– Lo suficientemente grande para manejar todas las
pilas que se van a usar generará gran cantidad de
espacio malgastado
– Una capacidad pequeña es inconveniente y molesto
porque los elementos no van a caber.

• Si usamos un vector dinámico, permitiremos al


usuario especificar el tamaño de la pila en su
declaración.
Problemas
• Si la pila está llena y se intenta agregar un
elemento, se producirá overflow

• Si definimos un tamaño muy grande


desperdiciaremos espacio

• Si definimos un tamaño pequeño hay


elementos que no cabrán en la pila.
Los cambios
• Ahora el constructor realmente tendrá que
construir algo: el vector que guardará los
elementos de la pila
• Queremos permitir declaraciones del tipo

Pila p1; // capacidad por defecto


Pila p2(cap); // capacidad definida por el int
cap
Algoritmo para el constructor
• Comprobar que la capacidad de la pila
(numElem) es >=0. Terminar si no lo es.
• Hacer miCapacidad =numElem
• Reservar espacio para un vector al que apunte
miVector y con capacidad miCapacidad
• si (hay memoria para este vector)
miTope = -1
sino
mostrar un mensaje de error
terminar la ejecución
Definición del constructor en el cpp
Pila::Pila (int numElem)
{
assert (numElem>0);
miCapacidad = numElem;
miVector = new () ElementoPila[miCapacidad];
if (miVector != 0)
miTope = -1;
else
{
cerr << “memoria insuficiente para crear la pila “;
exit (1);
}
}
Las otras operaciones
• Las operaciones vacía, apilar, tope, desapilar y
mostrar son las mismas que en la declaración
del vector estático.
Destructor
• Necesitaremos un destructor de la clase Pila
por la misma razón por la que se necesitaba el
constructor.

• La llamada al destructor liberará la memoria


reservada para el vector al que apunta
miVector
Destructor
En pila.h:
~Pila();

En pila.cpp:
Pila::~Pila()
{
delete [] miVector;
}
Pilas enlazadas
• Otra alternativa es usar una lista enlazada, lo
que le permitirá crecer sin límite (excepto la
memoria disponible) y achicarse para no
malgastar el espacio sin usar.
• Sólo el primer nodo de una lista enlazada es
directamente accesible y los elementos de la
pila sólo son accesibles desde el tope.
Pilas enlazadas

IMPLEMENTACIÓN DE
OPERACIONES
Constructor y vacia()
• Simplemente hacemos que miTope sea un
puntero nulo para mostrar que no se refiere a
ningún nodo
miTope = 0;

• Comprobar que esté vacía es preguntar si es 0


return miTope ==0;
apilar
• Una inserción al comienzo de la lista

miTope = new Pila :: Nodo (valor, miTope);


tope
return miTope-> dato;
desapilar
• Borrar el primer elemento

punt = miTope;
miTope = miTope-> siguiente;
delete punt;
Recuperar el primer elemento de la pila

1
miTope

4
desapilar
Repositorio de memoria

punt
miTope 2

4
Usos de las pilas
• Evaluación de expresiones en notación postfija
• Reconocedores sintácticos de lenguaje
• Recursividad
Ejercicios
• Escribir un programa que lea un string, carácter a carácter,
y determinar si el string contiene paréntesis equilibrados,
es decir, si cada paréntesis izquierdo se corresponde con
uno derecho más adelante en la cadena.
• Escribir un programa que convierta notación postfija en
notación infija, con los () puestos.

– Por ejemplo:
ab+ en a+b
a b + c d - * en (a+b)*(c–d)
Colas

Laboratorio de Programación II
Definición de cola
• Una cola es una línea de espera y como tal,
abunda en la vida cotidiana, en especial en
Argentina!

• Ejemplos:
– Fila de personas esperando el colectivo
– Fila de personas esperando para entrar al cine
– Fila de vehículos en un peaje
TAD cola
• Una cola es una clase especial de lista en la
cual las operaciones básicas de inserción y
borrado se restringen a los extremos de la
lista.
• Los elementos de la cola se eliminan por un
extremo, llamado frente (o cabeza) de la cola,
y se añaden por el otro, llamado final.
• Otras operaciones básicas son construir la cola
vacía y determinar si la cola está vacía.
TAD cola
• Operaciones básicas:
– Construcción (crear cola vacía)
– Vacía (comprobar si la cola está vacía)
– Insertar (agregar un nuevo elemento al final de la
cola)
– Frente (devuelve el elemento en el frente de la
cola)
– Eliminar (borra el elemento en el frente de la cola)
Colas enlazadas
• Así como una lista enlazada puede crecer al
añadírsele nuevos nodos, una cola enlazada
puede crecer tanto como sea necesario (o hasta
que se acabe la memoria disponible): no es
necesario fijar una cota superior de la capacidad
de antemano.

• Además la cola puede reducirse al eliminar


elementos devolviendo los nodos borrados al
repositorio de memoria.
Colas enlazadas
• Las listas enlazadas que vimos sólo nos daban
acceso al primer nodo de la lista manteniendo un
puntero a este nodo.
• Si hacemos que este primer nodo sea el frente de
la cola, las operaciones para acceder al primer
elemento o para eliminarlo se implementan de la
misma manera que las operaciones push y pop
de las pilas.
• Sin embargo, añadir valores al final de la cola
requeriría recorrer la lista entera cada vez para
encontrar el último elemento.
Colas enlazadas
• Este recorrido de la lista puede evitarse si
adoptamos el enfoque de las
implementaciones basadas en vectores vistas
en la teórica anterior, y mantenemos dos
punteros: miFrente, que apunta al nodo en el
frente de la cola, y miFinal, que apunta al
nodo final.
Colas enlazadas
• Por ejemplo, una cola enlazada con los
enteros 9, 17, 22, 26 y 34 en este orden,
podría dibujarse como:

miFrente 17 22 26
9 34

miFinal

También podría gustarte