Pilas En C++

82,660 views

Published on

Clase de Pilas en Estructuras de Datos

Published in: Education, Business, Technology
9 Comments
11 Likes
Statistics
Notes
No Downloads
Views
Total views
82,660
On SlideShare
0
From Embeds
0
Number of Embeds
892
Actions
Shares
0
Downloads
1,768
Comments
9
Likes
11
Embeds 0
No embeds

No notes for slide

Pilas En C++

  1. 1. PILAS EN C++ Prof. María A. García.
  2. 2. DEFINICIÓN <ul><li>Una pila es una estructura de datos homogénea (elementos del mismo tipo), secuencial y de tamaño variable. Sólo es posible un modo de acceso a esta estructura: a través de la cabeza de la pila. </li></ul><ul><li>De este modo podemos añadir un elemento a la cabeza de la pila o extraer un elemento de la cabeza de la pila. Debido a que las operaciones de extracción e inserción se realizan por el mismo extremo, el último elemento en ser añadido será el primero en ser extraído; por ello a estas estructuras se las conoce con el nombre de LIFO ( last-in, first-out; último en entrar, primero en salir). </li></ul>
  3. 3. La Pila GESTIÓN DE MEMORIA ESTÁTICA GESTIÓN DE MEMORIA DINÁMICA
  4. 4. Ejemplificaciones <ul><li>Un ejemplo típico de pila lo constituye un montón de platos: Cuando se quiere introducir un nuevo plato, éste se coloca en la posición más accesible, encima del último plato. Cuando se toma un plato, éste se extrae, igualmente, del punto más accesible, el último que se ha introducido. O, si somos más estrictos, otro ejemplo sería una caja llena de libros. Sólo podemos ver cuál es el libro que está más arriba en la caja, y si ponemos o tomamos un libro, sólo podremos actuar sobre este primer libro. No podemos siquiera saber el número total de libros guardados en la pila. Sólo sabremos el número de elementos de la pila de libros si previamente los sacamos hasta vaciar la caja. </li></ul>
  5. 5. Ejemplificaciones <ul><li>Otro ejemplo natural de la aplicación de la estructura pila aparece durante la ejecución de un programa de ordenador, en la forma en que la máquina procesa las llamadas a los procedimientos. Cada llamada a un procedimiento (o función) hace que el sistema almacene toda la información asociada con ese procedimiento (parámetros, variables, constantes, dirección de retorno, etc...) de forma independiente a otros procedimientos y permitiendo que unos procedimientos puedan invocar a otros distintos (o a si mismos) y que toda esa información almacenada pueda ser recuperada convenientemente cuando corresponda. Como en un procesador sólo se puede estar ejecutando un procedimiento, esto quiere decir que sólo es necesario que sean accesibles los datos de un procedimiento (el último activado, el que está en la cima). De ahí que una estructura muy apropiada para este fin sea la estructura pila. </li></ul>
  6. 6. Operaciones con Pila <ul><li>Asociadas con la estructura pila existen una serie de operaciones necesarias para su manipulación. Éstas son: </li></ul><ul><li>Iniciación de la estructura: </li></ul><ul><li>- Crear la pila (CrearPila): La operación de creación de la pila inicia la pila como vacía. </li></ul><ul><li>Operaciones para añadir y eliminar información: </li></ul><ul><li>- Añadir elementos en la cima (Apilar): pondrá un nuevo elemento en la parte superior de la pila. </li></ul><ul><li>- Eliminar elementos de la cima (Desapilar): lo que hará será devolver el elemento superior de la cima y eliminarlo de la pila. </li></ul><ul><li>- Operaciones para comprobar tanto la información contenida en la pila, como el propio estado de la cima: </li></ul><ul><li>- Comprobar si la pila está vacía (PilaVacia): Esta operación es necesaria para poder decidir si es posible eliminar elementos de la pila. </li></ul><ul><li>- Acceder al elemento situado en la cima (CimaPila): Nos indica el valor del elemento situado en la parte superior de la pila. </li></ul><ul><li>La especificación correcta de todas estas operaciones permitirá definir adecuadamente una pila. </li></ul>
  7. 7. Operaciones con Pila <ul><li>Una declaración más formal de las operaciones definidas sobre la estructura de datos pila, y los axiomas que las relacionan podrían ser las siguientes: </li></ul><ul><li>Estructura </li></ul><ul><li>Pila ( Valor ) / * Valor será el tipo de datos que podremos guardar en la pila */ </li></ul><ul><li>Operaciones </li></ul><ul><li>CREAR_PILA ( ) -> Pila </li></ul><ul><li>APILAR ( Pila , Valor ) -> Pila </li></ul><ul><li>DESAPILAR ( Pila ) -> Pila </li></ul><ul><li>CIMA_PILA ( Pila ) -> Valor </li></ul><ul><li>PILA_VACIA ( Pila ) -> Lógico </li></ul><ul><li>Axiomas </li></ul><ul><li>∀ stack ∈ Pila, x ∈ Valor se cumple que: </li></ul><ul><li>PILA_VACIA ( CREAR_PILA ( ) ) -> cierto </li></ul><ul><li>PILA_VACIA ( APILAR ( stack, x ) ) -> falso </li></ul><ul><li>DESAPILAR ( CREAR_PILA ( ) ) -> error </li></ul><ul><li>DESAPILAR ( APILAR ( stack, x ) ) -> stack </li></ul><ul><li>CIMA_PILA ( CREAR_PILA ( ) ) -> error </li></ul><ul><li>CIMA_PILA ( APILAR ( stack, x ) ) -> x </li></ul>
  8. 8. Implementación mediante estructuras estáticas <ul><li>La forma más simple, y habitual, de representar una pila es mediante un vector unidimensional. Este tipo de datos permite definir una secuencia de elementos (de cualquier tipo) y posee un eficiente mecanismo de acceso a la información contenida en ella. </li></ul><ul><li>Al definir un array hay que determinar el número de índices válidos y, por lo tanto, el número de componentes definidos. Entonces, la estructura pila representada por un array tendrá limitado el número de posibles elementos. </li></ul><ul><li>La parte privada de la clase, será pues un vector donde guardaremos la información. El primer elemento de la pila se almacenará en info[0], será el fondo de la pila, el segundo elemento en info[1] y así sucesivamente. En general, el elemento i-ésimo estará almacenado en info[i - 1]. </li></ul><ul><li>Como todas las operaciones se realizan sobre la cima de la pila, es necesario tener correctamente localizada en todo instante esta posición. Es necesaria una variable adicional, cima, que apunte al último elemento de la pila o nos diga cuantos elementos tenemos en ella. </li></ul>
  9. 9. Implementación mediante estructuras estáticas (Crear-Pila) <ul><li>Resumiendo, la clase Pila contendrá, en esta implementación, la iguiente parte privada: </li></ul><ul><li>class Pila </li></ul><ul><li>{ </li></ul><ul><li>public: ... </li></ul><ul><li>private: </li></ul><ul><li>Vector vect; </li></ul><ul><li>int cima; </li></ul><ul><li>}; </li></ul><ul><li>Donde Vector será: </li></ul><ul><li>typedef Valor Vector[MAX]; </li></ul><ul><li>Suponiendo Valor, el tipo de dato que se puede almacenar en la pila, y MAX una constante que me limita el tamaño máximo de la pila. </li></ul>
  10. 10. Implementación mediante estructuras estáticas (Crear-Pila) <ul><li>Operación CREAR_PILA </li></ul><ul><li>La creación de la pila se realizará mediante el constructor por defecto. La tarea que deberá realizar será decir que no existen elementos en la pila: </li></ul><ul><li>Pila::Pila (void) </li></ul><ul><li>{ </li></ul><ul><li>cima = 0; </li></ul><ul><li>} </li></ul>
  11. 11. Implementación mediante estructuras estáticas (Pila-Vacia) <ul><li>Operación PILA_VACIA </li></ul><ul><li>Esta operación permitirá determinar si es posible eliminar elementos. La pila estará vacía si la cima está apuntando al valor cero. </li></ul><ul><li>Algoritmo Pila_Vacia </li></ul><ul><li>Entrada </li></ul><ul><li>stack: Pila </li></ul><ul><li>Salida </li></ul><ul><li>( CIERTO, FALSO) </li></ul><ul><li>Inicio </li></ul><ul><li>Si ( stack.Cima = 0 ) entonces </li></ul><ul><li>Devolver ( CIERTO ) </li></ul><ul><li>Sino </li></ul><ul><li>Devolver ( FALSO ) </li></ul><ul><li>Fin_si </li></ul><ul><li>Fin ٭ </li></ul>bool Pila::PilaVacia (void) { return cima == 0; }
  12. 12. Implementación mediante estructuras estáticas (Apilar) <ul><li>Operación de inserción de información (APILAR) </li></ul><ul><li>La operación de inserción normalmente se conoce por su nombre inglés Push, o Apilar. La operación aplicada sobre un pila y un valor x, inserta x en la cima de la pila. Esta operación está restringida por el tipo de representación escogido. En este caso, la utilización de un array implica que se tiene un número máximo de posibles elementos en la pila, por lo tanto, es necesario comprobar, previamente a la inserción, que realmente hay espacio en la estructura para almacenar un nuevo elemento. Con está consideración, el algoritmo de inserción sería: </li></ul>
  13. 13. Implementación mediante estructuras estáticas (Apilar) <ul><li>Algoritmo Apilar </li></ul><ul><li>Entradas </li></ul><ul><li>x: Valor {* elemento que se desea insertar *} </li></ul><ul><li>stack: Pila de Valor </li></ul><ul><li>Salidas </li></ul><ul><li>stack </li></ul><ul><li>Inicio </li></ul><ul><li>{* comprobar si en la pila se pueden insertar más elementos *} </li></ul><ul><li>{* esto es necesario por el tipo de representación de la estructura *} </li></ul><ul><li>Si ( stack.Cima = MAX ) entonces </li></ul><ul><li>Error &quot; pila llena&quot; </li></ul><ul><li>Sino </li></ul><ul><li>stack.Cima ← stack.Cima + 1 </li></ul><ul><li>stack.Info [stack.Cima] ← x </li></ul><ul><li>Fin_sino </li></ul><ul><li>Fin </li></ul>bool Pila::Apilar (Valor x) { bool error; if (cima == MAX) error = true; else { error = false; info[cima] = x; cima++; } return error; } En la implementación en C++, tendremos en cuenta que vamos a devolver mediante la función si se ha producido algún tipo de error o no, en vez de mostrar un mensaje por pantalla.
  14. 14. Implementación mediante estructuras estáticas (Desapilar) <ul><li>La operación de borrado elimina de la estructura el elemento situado en la cima. Normalmente recibe el nombre de Pop en la bibliografía inglesa. El algoritmo de borrado sería: </li></ul><ul><li>Algoritmo Desapilar </li></ul><ul><li>Entradas </li></ul><ul><li>stack: Pila de Valor </li></ul><ul><li>Salidas </li></ul><ul><li>stack </li></ul><ul><li>x: Valor </li></ul><ul><li>Inicio </li></ul><ul><li>{* comprobar si se pueden eliminar elementos de la pila *} </li></ul><ul><li>{* esta operación no depende de la representación, siempre es necesaria *} </li></ul><ul><li>Si ( Pila_Vacia ( stack ) ) entonces </li></ul><ul><li>Error “ pila vacia” </li></ul><ul><li>sino </li></ul><ul><li>stack.Cima ← stack.Cima - 1 </li></ul><ul><li>Fin_si </li></ul><ul><li>Fin </li></ul>bool Pila::Desapilar (void) { bool error; if (cima == 0) error = true; else { error = false; cima--; } return error; }
  15. 15. Implementación mediante estructuras estáticas (Cima-Pila) <ul><li>Operación de consulta de información (CIMA_PILA) </li></ul><ul><li>La operación de consulta de la información, sólo puede acceder al elemento que esté situado en la cima de la pila, y proporcionar su valor. El algoritmo se limitará a devolver el elemento que está situado en la posición cima de la pila, si existe información almacenada en la pila. </li></ul><ul><li>Algoritmo Cima_Pila </li></ul><ul><li>Entradas </li></ul><ul><li>stack: Pila de Valor </li></ul><ul><li>Salidas </li></ul><ul><li>Valor </li></ul><ul><li>Inicio </li></ul><ul><li>{* comprobar si existe información en la pila *} </li></ul><ul><li>{* esta operación no depende de la representación, siempre es necesaria *} </li></ul><ul><li>Si ( Pila_Vacia ( stack ) ) entonces </li></ul><ul><li>Error “ pila vacia” </li></ul><ul><li>sino </li></ul><ul><li>Devolver ( stack.Info [stack.Cima] ) </li></ul><ul><li>Fin_si </li></ul><ul><li>Fin </li></ul>bool Pila::CimaPila (Valor & x) { bool error; if (cima == 0) error = true; else { error = false; x = info[cima - 1]; } return error; }
  16. 16. Implementación mediante estructuras dinámicas <ul><li>Uno de los mayores problemas en la utilización de estructuras estáticas, estriba en el hecho de tener que determinar, en el momento de la realización del programa, el valor máximo de elementos que va a poder contener la estructura. Una posible solución a este problema es la utilización de estructuras dinámicas enlazadas (utilización de punteros) tal y como se explicó en el primer cuatrimestre. </li></ul><ul><li>Por tanto, la clase Pila contendrá, en esta implementación, la siguiente parte privada: </li></ul><ul><li>class Pila </li></ul><ul><li>{ </li></ul><ul><li>public: ... </li></ul><ul><li>private: </li></ul><ul><li>Puntero cima; </li></ul><ul><li>}; </li></ul>Donde Puntero será: typedef struct Nodo * Puntero; el tipo Nodo será: struct Nodo { Valor info; Puntero sig; }; Suponiendo Valor, el tipo de dato que se puede almacenar en la pila. La implementación en este caso de los métodos de la clase Pila será la siguiente.
  17. 17. Implementación mediante estructuras dinámicas (Crear-Pila) <ul><li>Operación CREAR_PILA </li></ul><ul><li>stack: Pila </li></ul><ul><li>stack.Cima ← NULL </li></ul><ul><li>En C++: </li></ul><ul><li>Pila::Pila (void) </li></ul><ul><li>{ </li></ul><ul><li>cima = NULL; </li></ul><ul><li>} </li></ul>
  18. 18. Implementación mediante estructuras dinámicas (Pila-Vacia) <ul><li> Operación PILA_VACIA </li></ul><ul><li>Esta operación permitirá determinar si es posible eliminar elementos. La pila estará vacía si la cima está apuntando al valor cero. </li></ul>Algoritmo Pila_Vacia Entrada stack: Pila Salida ( CIERTO, FALSO) Inicio Si (stack.Cima = NULL) entonces Devolver ( CIERTO ) Sino Devolver ( FALSO ) Fin_si Fin bool Pila::PilaVacia (void) { return cima == NULL; } ٭
  19. 19. Implementación mediante estructuras dinámicas (Apilar) <ul><li> Operación de inserción de información (APILAR) </li></ul><ul><li>Con la representación enlazada de la pila, la estructura tiene una menor limitación en cuanto al posible número de elementos que se pueden almacenar simultáneamente. Hay que tener en cuenta que la representación de la pila ya no requiere la especificación de un tamaño máximo, por lo que mientras exista espacio libre en memoria se va a poder reservar espacio para nuevos elementos. Por esa razón, se va suponer en el siguiente algoritmo que la condición de pila llena no se va a dar y, por lo tanto, no será necesaria su comprobación. </li></ul>
  20. 20. Implementación mediante estructuras dinámicas (Apilar) <ul><li> Algoritmo Apilar </li></ul><ul><li>Entrada </li></ul><ul><li>stack: Pila de Valores </li></ul><ul><li>x: Valor </li></ul><ul><li>Salida </li></ul><ul><li>stack </li></ul><ul><li>Variable </li></ul><ul><li>p_aux: Puntero_a_Nodo_pila </li></ul><ul><li>Inicio </li></ul><ul><li>p_aux ← Crear_Espacio </li></ul><ul><li>p_aux^.Info ← x </li></ul><ul><li>p_aux^.Sig ← stack.Cima </li></ul><ul><li>stack.Cima ← p_aux </li></ul><ul><li>Fin </li></ul>bool Pila::Apilar (Valor x) { bool error; Puntero p_aux; error = false; p_aux = new Nodo; p_aux->info = x; p_aux->sig = cima; cima = p_aux; return error; }
  21. 21. Implementación mediante estructuras dinámicas (Desapilar) <ul><li>Operación de eliminación de información (DESAPILAR) </li></ul><ul><li>La único que hay que tener en cuenta a la hora de diseñar un algoritmo para esta operación es la utilización eficiente de la memoria, de forma que el espacio ocupado por el nodo borrado vuelva a estar disponible para el sistema. Recordar que si la pila está vacía no se puede desapilar. </li></ul>
  22. 22. Implementación mediante estructuras dinámicas (Desapilar) <ul><li>Algoritmo Desapilar </li></ul><ul><li>Entrada </li></ul><ul><li>stack: Pila de Valor </li></ul><ul><li>Salida </li></ul><ul><li>stack </li></ul><ul><li>x: Valor </li></ul><ul><li>Variable </li></ul><ul><li>p_aux: Puntero_a_Nodo_pila </li></ul><ul><li>Inicio </li></ul><ul><li>Si ( Pila_Vacia (stack) ) entonces </li></ul><ul><li>Error “ pila_vacia” </li></ul><ul><li>Sino </li></ul><ul><li>p_aux ← stack.Cima </li></ul><ul><li>stack.Cima ← p_aux^.Sig </li></ul><ul><li>Liberar_Espacio (p_aux) </li></ul><ul><li>Fin_si </li></ul><ul><li>Fin </li></ul>bool Pila::Desapilar (void) { bool error; Puntero p_aux; if (cima == NULL) error = true; else { error = false; p_aux = cima; cima = cima->sig; delete p_aux; } return error; }
  23. 23. Implementación mediante estructuras dinámicas (Cima-Pila) <ul><li>Operación de consulta de información (CIMA_PILA) </li></ul><ul><li>Al elemento &quot;visible&quot; de la pila se puede acceder fácilmente a través del puntero que le referencia, cima, que siempre debe existir y ser adecuadamente actualizado. </li></ul><ul><li>Algoritmo Cima_Pila </li></ul><ul><li>Entradas </li></ul><ul><li>stack: Pila de Valor </li></ul><ul><li>Salidas </li></ul><ul><li>Valor </li></ul><ul><li>Inicio </li></ul><ul><li>{* comprobar si existe información en la pila *} </li></ul><ul><li>{* esta operación no depende de la representación, siempre es necesaria *} </li></ul><ul><li>Si ( Pila_Vacia ( stack ) ) entonces </li></ul><ul><li>Error “ pila vacia” </li></ul><ul><li>sino </li></ul><ul><li>Devolver (Cima^.Info) </li></ul><ul><li>Fin_si </li></ul><ul><li>Fin </li></ul>bool Pila::CimaPila (Valor & x) { bool error; if (cima == NULL) error = true; else { error = false; x = cima->info; } return error; }

×