lunes, 22 de noviembre de 2010

.: Pila :.

:: Concepto de Pila e Implementación ::



Materia. Lab de Leng de Progr
Hora. V1 (Jueves)

Volviendo a recordar ciertas cosas que en teoría conocemos, ahora hablaremos acerca de las pilas.
Para empezar, hay que reconocer lo que es una pila.
Podemos decir que una pila es una estructura de datos que obedece siguiente disciplina:
“LIFO (Last In, First Out): El último en entrar es el primero en salir”.
Las funciones principales asociadas con las pilas son las siguientes:
  • Push. Insertar un elemento.
  • Pop. Extraer un elemento.
Veamos cómo se vería el ingreso y extracción de elementos en una pila por medio de la siguiente imagen:
Cuando nosotros tenemos por ejemplo la siguiente operación en notación sufija:
7 3 – 2 1 + *
Se implementa una pila para esto, de modo que tendríamos lo siguiente:

La forma en la cual se lee esto es la siguiente:
Cuando se lee un operando (número), se ingresa a la pila.
Al momento de leer un operador, como en el primer caso que fue el de suma (+), se toman los últimos dos números ingresados a la pila y se realiza la operación ingresada para tener un nuevo valor.
Se vuelven a leer números y se van ingresando a la pila y al momento de ingresar un operador se leen los últimos dos elementos de la estructura para realizar la operación.
Todo esto hasta terminar.
Quizás no quedo muy claro, por lo que se los expondré así:
Visualicen cuando manejamos nuestros programas con subrutinas.
Estamos haciendo un proceso en nuestra función main, y de repente necesitamos un resultado que debe adquirirse por medio de una función.
Entonces, es como si el proceso de main estuviera dentro de una pila, y al momento de mandar llamar la función que necesitamos, ésta es introducida a la pila.
Al momento que la función termina lo que debe de hacer, es como si la función saliera de la pila dejándole o devolviéndole el valor que obtuvo a main para que pueda continuar con el proceso en el cual se quedó.
Nosotros manejamos pilas a cada momento, no sólo en el manejo de subrutinas, sino también por ejemplo las vemos en las siguientes aplicaciones:
  • Historial de Internet
  • Portapapeles de Office
  • Los botones de ATRÁS y ADELANTE del explorador de Windows e IE.
  • Los documentos que se encuentran pendientes para imprimir obedecen el comportamiento LIFO.
  • Entre otros.
Cuando me tocó ver lo que era la estructura de pilas en la clase de Estructuras de Datos, creamos un pequeño programa, el cual tiene las siguientes opciones:
1. Introducir datos a la pila
2. Borrar un dato de la pila
3. Mostrar elemento en el tope de la pila
4. Imprimir elementos de la pila
Cada una de estas opciones está siendo manipulada a través de un SWITCH. Antes de proseguir, aclaro que en sí nuestra “PILA” está siendo implementada a través de lo que es un “ARRAY” de tamaño 15. Sé que no es precisamente la estructura de pila que quizás esperaban ver, pero recuerden que en sí el propósito de esta entrada es la comprensión del concepto pila.
Ahora pasemos a detallar las acciones para cada función.
Introducir datos a la pila.
printf("\n\nDame el valor: ");
scanf("%d", &temp);
tope ++;
pila[tope + 1] = temp;
Nosotros tenemos una variable temp de tipo entero que funciona como la “celda” de nuestra pila donde vamos a estar guardando datos.
Tenemos la variable de tipo entero llamada “tope”, que funciona como nuestro indicador de la cima de la pila, la cual, a la vez, también le asignamos el valor de “-1”. Después explicaremos por qué se usó de esta forma.
Nuestra “pila” como ya mencionamos, es un arreglo “pila[15]”.
Pasando al proceso del ingreso de datos a la pila, nosotros ingresamos un número que se guardará en la variable “temp”. Lo siguiente fue incrementar el valor de “tope” en una unidad, para después pasar a utilizar el valor de tope como índice de nuestro arreglo “pila”.
 ¿Recuerdan que “tope” valía al inicio “-1”? Esto fue así, debido a que al momento de ingresar el primer dato a la pila, ahora “tope” se incrementaría a “0”, y recuerden que los arreglos empiezan desde la posición “0”. A esto se debía la naturaleza de haber asignado el valor de “-1” a la variable que utilizaríamos como nuestro indicar de la cima de la pila.
Por último, el valor de “temp” se asigna a la posición “tope” de nuestro arreglo “pila”.
Ingreso de Datos
Imprimir Elementos de la pila
Para esto, recuerden que nuestra implementación de pila es un arreglo, por lo que se utiliza un FOR para mostrar datos introducidos.
Sin embargo, tenemos una restricción. Teniendo de nueva cuenta el valor de “tope = -1”, aquí lo usamos de base para decir si la pila se encuentra vacía a través de un IF; de lo contrario, nos mostrara el contenido de la pila.
if (tope <= -1) {
        printf("\n\nLa pila se encuentra vacia\n\n");
} else {
        for (i = tope; i > -1; i--) {
               printf("\t\t\t|   %d   |\n", pila[i]);
         }
}
Como se pudieron percatar, la forma en que mandamos imprimir nuestro “arreglo (alias pila)”, es de una manera inusual a como solemos hacerlo normalmente. Por lo común iniciamos desde el primer elemento del arreglo, o sea desde “0”.
Pero recuerden que la pila obedece la disciplina LIFO. Esto significa que primero debemos mostrar el último elemento que entro a nuestro “arreglo”...  perdón,  nuestra “pila”.
Entonces, la impresión debe ir desde el último elemento hasta cuando el valor de “tope” sea mayor a “-1”, porque recuerden que con ese valor, definimos que la pila está vacia. Obviamente el valor de tope irá decreciendo en cada impresión.
¿Pero cómo saber desde que posición comenzará a imprimir? Recuerden que al momento de capturar datos, “tope” se incrementa en una unidad por cada lectura; por consiguiente tenemos un contador en automático.
Veamos cómo se vería ingresar números del 1 hasta el 5:
Impresión de Elementos en la pila
Mostrar elemento en el tope de la pila.
Esta función no tiene gran ciencia, simplemente mandamos a imprimir el elementos de la  ”pila” que se encuentra en la posición “tope”, dependiendo de cuál sea el valor de esta variable en ese momento debido al número de datos ingresados en la pila.
También nos seguimos basando en la restricción del valor de “tope” para saber si la pila se encuentra vacía.
if (tope <= -1) {
      printf("\n\nLa pila se encuentra vacia\n\n");
} else {
       printf("\n\n\t\t\t|   %d   |\n", pila[tope]);
}

Elemento en el tope de la pila
 Borrar un dato de la pila
Por último mostramos el proceso para “borrar” un elemento de la pila.
Para esto, sólo basta una instrucción que decrementa el valor de “tope” en una unidad.
tope = tope - 1;
¿Qué pasa si entro dos veces a esta opción y después muestro los elementos de la pila? Veamos.

Eliminación de dos elementos de la pila para después mostrar los restantes
 ¿Notaron el cambio?
NOTA. Hago la aclaración, en realidad, no borramos el dato de la pila (que vuelvo a lo mismo, es un arreglo), simplemente con el hecho de retarle 1 al valor del tope en cada entrada a esta función es para que al momento de mostrar los datos, el programa imprima desde el valor actual de tope. ¿Recuerdan cómo tenemos el FOR? A eso me refiero.
Vuelvo a lo mismo, este código es sólo para dejar lo más claro posible el concepto de lo que es pila.
Lo que se hizo con estas funciones fue sólo demostrar el comportamiento LIFO de lo que es la estructura pila.
Les dejo el código a continuación.
Comentarios y sugerencias son bienvenidas.
Saludos.

2 comentarios:

  1. Te puse +4 en la clase; en lab ya estás encima de cien.

    ResponderEliminar
  2. quisiera ver el codigo del programa de pilas, por favor....Gracias

    ResponderEliminar