Vous êtes sur la page 1sur 22

lvarez, Mara

Fajardo, Daniel
Sendn, Alba

INCIDE:
Definicin de Pilas
Concepto de Pila.3
Operaciones fundamentales3
Otras operaciones...4

Utilidades de las Pilas


Llamadas a subprogramas..5
Paso de programas recursivos a iterativos..6
Equilibrado de smbolos.7
Tratamiento de expresiones aritmticas.9
Transformacin de notacin infija a postfija.10
Evaluacin de la notacin postfija.12

Implementacin de las Pilas.


Implementacin mediante vectores14
Implementacin mediante listas enlazadas.16

Programa Demo.
Referencias.

DESCRIPCIN DE PILA
DEFINICION: Una pila (stack) es un tipo fundamental de lista (Tipo de dato
abstracto fundamental) en la que todas las inserciones y supresiones de
elementos solo se pueden realizar desde una nica posicin, el extremo, la cima
o tope de la pila (TOP).
El modelo intuitivo de una pila es precisamente una pila de monedas
puestas sobre una mesa, o de cajas sobre el piso, o de bandejas en una estantera,
situaciones todas en las que solo es conveniente quitar o agregar un objeto del
extremo superior de la pila, al que se denominara en lo sucesivo tope.

Dado que las operaciones de aadir solo se realizan por el extremo


superior de la pila, los elementos solo se pueden eliminar en orden inverso a
como han sido insertados en la pila. Por esta razn a las pilas se las conoce como
listas LIFO (last input, first output), ya que el ltimo elemento en entrar ser el
primero en salir.
Las tres operaciones ms importantes un una pila son:

PUSH: Meter, poner, apilar. Operacin que inserta un elemento en la


sima de la pila.
POP: Sacar, quitar, desapilar. Operacin que elimina el elemento que
ocupaba la posicin cima. El elemento que haba sido insertado inmediatamente
antes que el eliminado pasara a ha ser ahora la nueva posicin cima.
TOPE: Operacin que devuelve el elemento que ocupa en ese instante la
posicin cima pero sin extraerlo.
A aparte de estas operaciones, que son las fundamentales, cuando
queremos trabajar con pilas tendremos que utilizar ms operaciones, sobre todo
necesarias cuando se trata de pilas usando listas enlazadas.
Dichas operaciones son las siguientes:

CREAR: Lo que hace esta operacin es inicializar una pila como pila
vaca.
BORRAR: Esta operacin lo que hace es convertir una pila P en una pila
vaca.
VACIA?: Devuelve verdadero si la pila no tiene elementos, y falso en
caso contrario. No podremos hacer POP ya que se producira un desbordamiento
negativo (underflow) al no tienen ningn elemento que eliminar.
LLENA?: Ocurre lo mismo que con el caso VACIA? Solo que en este
caso te devuelve verdadero si la pila esta llena y no podemos insertar ningn
elemento ms a no ser que eliminemos alguno antes. Si tratsemos de insertar un
elemento ms se producir un error a causa de un desbordamiento (overflow).
Las pilas pueden representarse grficamente de varias maneras, entre las
cuales destacan las siguientes.

A partir de ahora, para seguir dando propiedades de las pilas y sus


operaciones, tendremos que distinguir entre pilas definidas mediante vectores o
mediante listas enlazadas, pero eso lo veremos ms adelante.

UTILIDADES DE LAS PILAS


Las pilas, adems de simplificar algoritmos complejos y permitir acceso rpido a
otros programas, son utilizadas ampliamente para solucionar una gran variedad de
problemas. Se utilizan en compiladores, sistemas operativos y en programas de
implementacin. Veamos alguna aplicacin interesante de las pilas.

Llamadas a subprogramas:

Cuando dentro del programa principal tienes subrutinas o funciones a las


que tienes que llamar, el programa principal tiene que recordar el lugar donde
hizo la llamada y guardar el estado en el que se encontraba el programa en ese
momento, con sus variables y valores previos a la llamada para poder retomar
cuando el subprograma haya finalizado, ya que de otra forma el procedimiento
sobrescribir en ellas. Todo ellos se guarda en una pila.
Cuando, adems, se trata de programas con llamadas recursivas es de
gran utilidad, ya que al hacer tantas paradas unas dentro de otras, si no se
controla el tamao de la pila, se puede producir un desbordamiento.
Veamos con ms claridad como funciona una pila para las llamadas a los
subprogramas mediante un ejemplo.
Tenemos el programa principal con los subprogramas A, B, C, donde el
programa principal llama al subprograma A, y este, una vez ejecutndose, llama
al subprograma B. El programa B tiene una llamada al subprograma C, entonces
el PPABC. B no continua la ejecucin hasta que termina el subprograma
C, y A no termina la suya hasta que no termina el B. Lo mismo ocurre con el
programa principal. Luego:

Esta operacin se consigue mediante una pila que


en la que se guardan las direcciones de retorno.

Cuando un programa o subprograma llama a otro, la direccin se


introduce en la pila, por supuesto en la cima, y cuando un subprograma termina,
vuelve a la direccin siguiente a la instruccin en la que se llamo, y de este
modo, la pila se va vaciando y el puntero de la pila queda libre siempre
apuntando a la siguiente direccin de retorno, de la siguiente forma:

Paso de programas recursivos a iterativos.

La recursin es un mtodo muy utilizado y una herramienta muy valiosa


y poderosa a la hora de crear algoritmos claros y concisos que se utiliza para
problemas que se resuelven resolviendo ese mismo problema pero en una
dimensin ms pequea una y otra vez hasta llegar al problema base y luego dar
marcha atrs, es decir, problemas que se definen en trminos de s mismos, que
se repiten una y otra vez a ellos mismos para calcular una solucin. Pero el uso
de la recursin es costoso en trminos de consumo de memoria. Si adems
tenemos en cuenta que muchos lenguajes de programacin no cuentan con la
facilidad de implementar programas recursivos, seria bueno encontrar un
procedimiento alternativo que permita simularlo.
Pero para simular un programa recursivo es necesario la utilizacin de
pilas, ya que se esta llamando continuamente a subprogramas que a la vez
vuelven a llamarse a si mismo. Cada vez que un subprograma hace una llamada,
hay que guardar la direccin a la cual debe regresar cuando acabe de ejecutar el
subprograma llamado y las variables y valores actuales antes de la llamada, pues
de lo contrario estos valores podran ser sobrescritos.
Cada coleccin de variables que se guarda antes de hacer una llamada se
llama registro de activacin.
Veamos como se utiliza esta eliminacin de la recursin mediante un
ejemplo sencillo hecho en clase. El clculo del nmero factorial.
El programa principal es de la forma:
main ( ) {

int n, factorial ();


scanf (%d, &n);
printf (Este es el factorial de %d: %d, n, factorial(n));
}
int factorial (int n) { /*funcin recursiva que calcula el factorial*/
if (n == 1 or n == 0)
return 1; /*caso base*/
else
return (n*factorial (n-1));
}

Cuando le damos un valor a n, al llamar al subprograma por primera vez


tendremos que guardar esa n en alguna parte. Este valor lo guardo en la pila, que
para este tipo de informacin es una estructura muy adecuada, ya que sta no va
a poder ser utilizada hasta que termine la llamada al subprograma. La forma de
guardar los datos es la siguiente:
A medida que se van realizando llamadas, se van guardando los valores
de n (guardados en los registros de activacin) en la pila; as, los valores
correspondientes a llamadas ms externas estarn ms abajo en la pila, y los
correspondientes a llamadas ms internas, ms arriba.
Una vez que haya concluido este proceso, lo que hace el programa es
sacar el tope de la pila, sacar el nuevo tope y multiplicarlos, y luego ir sacando
iterativamente los topes y multiplicndoles por el producto anterior.

Equilibrado de smbolos.
Tambin pueden utilizarse las pilas para revisar programas en busca de
errores, como por ejemplo en el caso de los smbolos.
En cada compilador se utilizan las pilas para comprobar si se han
producido errores, para que cada parntesis, llave o corchete de apertura tenga su
correspondiente cierre. Es decir, que si un programa presenta ms smbolos de
apertura que de clausura, el programa tendra errores y no seria vlido.
Tambin tenemos que tener en cuenta el orden en el que estn dichos
smbolos, porque puede que aunque tenga los mismos smbolos de apertura que
de clausura, tenga errores, ya que dichos smbolos no estn colocados
correctamente. Por ejemplo, si nos encontramos en este caso: ([{])} el programa
dara un error, ya que la segunda llave no esta colocado en su lugar y trastocara
toda la estructura interna del programa.

Para ello puede crearse un programa que dado un fichero en el lenguaje


del compilador correspondiente nos diga si hay algn tipo de error en la
anidacion de los smbolos mediante la utilizacin de pilas. El programa
funcionaria de la siguiente forma:
Creamos un pila vaca de caracteres y se abre el fichero en el que se
encuentra el programa. Se leen uno a uno los caracteres, pero solo nos quedamos
con aquellos que sean parntesis, corchetes o llaves. Cuando nos encontremos
con un carcter de apertura lo metemos en la pila y seguimos leyendo caracteres
hasta que lleguemos al siguiente. Mientras sea un carcter de apertura, se mete
en la pila.

Cuando nos encontremos con un carcter de clausura, lo que tenemos que


hacer es mirar a la cima de la pila. Si lo que nos encontramos es el smbolo de
apertura correspondiente al smbolo que estamos mirando, lo sacamos de la pila,
en caso contrario, se mete en la pila. Y as sucesivamente hasta que hayamos
ledo todo el fichero.

Una vez finalizada la lectura del fichero sabremos si estn bien anidados,
y por lo tanto si el programa es aparentemente correcto si y solo si la pila esta
vaca, ya que cada smbolo que hemos abierto, lo habremos cerrado
correctamente.
Pero este programa tiene una pega, ya que si el fichero que estamos
leyendo con el contenido del programa tiene comentarios en los que escribe
smbolos no anidados o errneamente colocados, no afectara al programa que
queremos revisar ya que es un comentario, pero si que afectara al nuestro, ya
que la pila no quedara vaca. Es decir, que un trozo de cdigo bien hecho puede
interpretarse como un trozo con errores. Algn ejemplo:
/*Con un comentario as ( [ ) ] el programa nos dara un error*/
Printf (con una expresin as tambin nos dara un error %c:, })
Por lo tanto si queremos utilizar este programa para depurar errores un
nuestro programa, tendremos que asegurarnos previamente de que los
comentarios que hemos puesto son correctos y que no pueden inducir a error al

igual que los smbolos que utilizamos como escritura tampoco nos van a dar
ningn problema.
Para un programa como este emplearemos listas enlazadas, pues no
sabemos cual es la longitud del fichero y tampoco cual es la cantidad de
smbolos que este contiene, por lo que un vector podra quedarse corto o pasarse
de largo.

Tratamiento de expresiones aritmticas:


Una expresin aritmtica esta formada por operandos y operadores, como
por ejemplo (a+b) - c*d. En este caso +, -, * son los operadores y a, b, c, d los
operandos. Los operandos pueden ser valores, variables o incluso otras
expresiones, mientras que los operadores son los conocidos de las expresiones
matemticas, por lo que el resultado puede ser de tipo numrico o variables.
La forma habitual que tenemos de escribir las operaciones matemticas
es poniendo el operador entre dos operando, y que puede llevar parntesis para
encerrar subexpresiones con mayor prioridad en cada operacin, al igual que los
operadores tienen cada uno una prioridad diferente, ya que, por ejemplo, la
multiplicacin * tienen prioridad sobre la suma +.Veamos el grado de prioridad
de estos operadores.
1.
2.
3.
4.

Parntesis ( )
Potencial ^
Producto/cociente * /
Suma/resta + -

Tambin hay que tener en cuenta que cuando se evala una operacin se
hace de izquierda a derecha, excepto en el caso de las potencias, que se hace de
derecha a izquierda.
Esta forma de escribir una expresin, se denomina notacin usual o
infija.
Existen otras formas de escribir expresiones aritmticas, en el que se
diferencian por la situacin de los operadores respecto de los operandos. La
forma en la que los operadores se colocan delante de los operandos es conocida
como notacin polaca o prefija.
Vemos un ejemplo:
Notacin infija: a*b/(a+c)

Notacin polaca: */ab+ac

Adems de estas existe otro tipo de notacin, el que a nosotros ms nos


interesa, que es la notacin postfija, en la que se colocan los operadores a

continuacin de los operandos, y en la cul no existe jerarqua en las


operaciones.
Las diferentes formas de escribir una misma expresin algebraica
dependen de la ubicacin de los operadores respecto a los operandos. Es
importante tener en cuenta que tanto en la notacin prefija como en la postfija no
son necesarios los parntesis para cambiar el orden de evaluacin. Veamos
algunos ejemplos de notacin infija respecto de la notacin postfija

Notacin infija

Notacin postfija

2*(3+8/(6-4))

23864-/+*

3+2*7-1

327*+1-

1*2*3*4+5

12*3*4*5+

Vemos que hacemos lo mismo que haramos en notacin infija y no


hemos tenido que acudir a parntesis ni a jerarquas de operaciones. Por eso la
evaluacin de expresiones postfijas es muy fcil de implementar.
A la hora de evaluar una expresin aritmtica de notacin infija,
tendremos que realizar dos pasos:

Transformacin de notacin infija a notacin postfija.


Evaluacin de la notacin postfija.

Para ello tendremos que emplear un tipo TDA pila. Veamos que ocurre
en cada uno de los casos.

Transformacin de notacin infija a notacin postfija


Partimos de una expresin con notacin infija que tiene operadores y
operandos, que queremos transformar en una notacin postfija.
La transformacin se realiza mediante la utilizacin de una pila en la que
se van metiendo los operadores y los parntesis izquierdos. La expresin
aritmtica se va leyendo carcter a carcter y va guardndose en una pila o en un
array, segn de lo que se trate, de la siguiente forma:
Si es un operando, se guardara directamente en el array o en un
fichero.
Si es un operador y la pila est vaca, lo meteremos en la pila. Si la
pila no esta vaca, tendremos que distinguir el grado de prioridad de
dicho operador. Por lo tanto:
Si la cima de la pila es un operador de menor prioridad, entonces
lo meteremos en la pila.

10

Sin embargo si la cima de la pila es un operador de mayor o igual


prioridad, entonces tendremos que sacar los operadores de la pila
uno a uno y los escribiremos en el array o fichero hasta que en la
cima haya en operador de menor prioridad, un parntesis de
apertura o hasta que la pila quede vaca. Ser entonces cuando
metamos el operador. De esta forma nos aseguramos de que las
operaciones con mayor prioridad se realizan anteriormente, pues
sus operadores son los que antes salen de la pila
Si es un parntesis tendremos que distinguir los dos casos existentes:
Si es un parntesis de apertura se mete en la pila, se considerara
de menor prioridad para todo.
Cuando se lee el otro parntesis de clausura hay que sacar todos
los operadores de la pila que pasaran a formar parte de la notacin
postfija hasta llegar al parntesis de apertura, que se eliminara, ya
que los parntesis no forman parte de la notacin postfija.
De esta forma aseguramos que las operaciones contenidas en un
parntesis van a ser agrupadas.
El proceso se termina cuando ya no hay mas tems que leer, y es entonces
cuando sacamos uno a uno los operadores que pudieran quedar en la pila y los
escribimos al final de nuestro array o fichero. Todo habr concluido cuando no
haya nada ms que leer y la pila este vaca.
En estos casos tambin es conveniente utilizar pilas implementadas
mediante listas enlazadas, ya que no sabemos cual va a ser la longitud de la pila
y si utilizamos un vector podemos quedarnos cortos o pasarnos de largo.
Veamos algn ejemplo que nos aclare las cosas:
a*(b+c-(d/e^f)-g)
a
ab
abc

el operando a pasa a un fichero o array, y * a la pila


el ( pasa a la pila y el operando b pasa al fichero
el + pasa a la pila y el operando c se escribe en el fichero

La pila tiene la siguiente forma:

+
(
*

Se nos presenta el problema del -, que como tiene


igual prioridad que el + se saca +, se escribe en el
fichero y se mete en la pila.

abc+
abc+de
abc+def

(
*

el ( se escribe en la pila
el operando d pasa al array, el / a la pila, y e pasa al array
^ lo metemos en la pila, y f lo escribimos en el fichero.

11

Ahora se cierra un parntesis y tenemos la siguiente pila:


^
/
(
(
*
Luego nuestra expresin quedar, tras haber sacado los operadores hasta
parntesis y eliminndolo despus de haberlo sacado as: abc+def^/

abc+def^/-g

el se compara con la cima de la pila, que al ser de igual prioridad


se escribe en el array o fichero y en se mete en la pila.

abc+def^/-g- al terminar el otro parntesis, escribimos todo lo que hay en la


pila hasta llegar al parntesis de apertura. La pila ser ahora de la
forma:
*
Como ya no hay mas tems escribimos el contenido de la pila al final de
la notacin postfija, y la pila quedar vaca, y el resultado ser: abc+def^/-g-*

Evaluacin de la notacin postfija:

Cuando tenemos una expresin aritmtica en notacin postfija, con


valores reales, y queremos evaluarla, lo que tendremos que hacer ser utilizar
una pila de operandos, es decir, de nmeros reales.
Tendremos un algoritmo que evaluar la expresin, leyendo los datos de
la expresin uno a uno y tratndolos segn su tipo.
Si es un nmero real, lo meteremos en la pila.
Si es un operador, lo que haremos ser sacar dos nmeros reales de la
pila y les aplicaremos el operador sobre ellos. El resultado lo
meteremos en la pila. Hay que tener en cuenta a los operadores resta
y cociente (- y /) ya que en ocasiones no nos es indiferente el orden
de los nmeros. Para ellos, el elemento que antes hubiese entrado en
la pila, es decir, el que sacamos en segundo lugar, ser el que
aparezca a la izquierda del operador.
Resumidamente, se trata de recorrer la expresin y cada vez que
encontremos un operador, se lo aplicamos a los dos ltimos nmeros que

12

hayamos introducido en la pila. Entonces el nmero real que quede en la pila


ser el resultado.
Tanto en este caso, como en el anterior, como no sabemos el tamao de
la expresin, ser mejor utilizar pilas implementadas mediante listas enlazadas.
Veamos un ejemplo de la evaluacin de la notacin postfija:
Evaluemos la expresin postfija: 327*+1-
Tendremos una pila de la forma:
7
2
3

Y nos encontramos con un operador *, y lo que hacemos es:

TOPE (Pila) = 7
POP (Pila)
TOPE (Pila):=2
POP (Pila)
7*2=14
PUSH (pila, 14)
14
3
Ahora nos encontramos con el operador +, y procedemos de igual
manera:
TOPE (Pila)=14
POP (Pila)
TOPE (Pila)=3
POP (Pila)
14+3=17
PUSH (Pila, 17)
PUSH (Pila, 1)
1
17
Nos encontramos con el operador - .
Lo que hacemos es sacar los dos valores de la pila con y resolver, y ese
ser el resultado: 17 1= 16
Por lo tanto 327*+1- = 16

13

IMPLEMENTACIN DE LAS PILAS:


Mediante vectores:
Una pila puede implementarse mediante vectores, en cuyo caso la dimensin
es fija. En este caso se dir que es una implementacin esttica. Cuando lo
implementamos mediante un vector hay que tener en cuenta que el tamao de la pila
no puede exceder el nmero de elementos del array.
Definiremos, antes de implementar una pila mediante vectores, el nmero
mximo de elementos que podremos meter en el apila. Ser n
La declaracin de pila es:
Elemento = E;
Pila = registro de
cima: numrico;
arreglo: vector [1n] de elemento:
fin registro;
Luego la pila ser:

Donde cima corresponde a la posicin en el vector del ltimo elemento


insertado en la lista, o sea que a de apuntar en todo momento al elemento tope.
As si pila.cima=01 entenderemos que la pila esta vaca, mientras que si
pila.cima = n la pila estar llena.
Esta implementacin no es apropiada cuando no se conoce el nmero
mximo de elementos que puede tener una pila ya que podra quedarse corta por
faltarle posiciones, y se producira un error, o por pasarse de larga, es decir,
utilizar mucha ms memoria de la estrictamente necesaria y desaprovecharla. De
todas formas, esta implementacin tiene una gran ventaja, que es la sencillez y
rapidez con la que se programa y se realizan las operaciones.
Veamos cuales son las operaciones bsicas:
#defina tam_max 20 /*este ser el tamao mximo (20), se puede cambiar*/
Typedef int elemento; /*ser una pila de enteros*/
Typedef struct {
int cima;
elemento v[tam_max];

14

}pila;
/*El tipo elemento variar, al igual que el tam_mx, dependiendo del
programa*/

Crear_Pila (PILA *P){


Pila.cima = tam_max;
}

/*Creamos una pila vaca*/

Borrar_Pila (PILA *P){


while(!VACIA(P))
POP(P);
}

/*Borramos una pila, la dejamos vaca*/

Vacia? (PILA *P){


if (pila.cima == tam_max){
return 1;
}
else {
return 0;
}
}

/*Preguntamos si la pila est vaca*/

Llena? (PILA *P){


if (pila.cima == 0){
return 1;
}
else {
return 0;
}
}

/*Comprobamos si la pila esta llena*/

PUSH (PILA *P, elemento x){


int copia_cima, valor_llena;
valor_llena = llena?(P);
if (valor_llena == 1) {
return 0;
}
else {
copia_cima = *P.tope;
*P.v[copia_cima-1] = x;
*P.cima = copia_cima-1;
return 1;
}
}

/*Inserta un elemento en la pila(si puede)*/

15

POP (PILA *P){


/*Elimina el primer elemento del vector, la cima*/
int valor_vacia;
valor_vacia = Vacia?(P);
if (valor_vacia == 1){
return 0;
}
else{
*P.cima = *P.cima+1;
return 1;
}
}

TOPE (PILA *P){


/*Te devuelve el tope de la pila*/
int copia_cima;
if ( vacia?(P) == 0){
copia_cima = P.cima;
return P.v[copia_cima];
}
else{
printf(\nError. Has aplicado la funcin tope a una pila vacia\n);
}
}

Mediante listas enlazadas:


La realizacin dinmica de una pila se hace almacenando los elementos
como nodos de una lista enlazada, con la particularidad de que siempre que se
desee hacer una operacin sobre ella se hace por el mismo extremo que se
extrae.
Esta realizacin tiene la ventaja de que el tamao se ajusta exactamente a
los elementos de la pila, no hay un mximo de elementos, por lo tanto tampoco
puede haber una lista llena. Sin embargo, para cada elemento es necesaria ms
memoria ya que hay que guardar el campo de enlace.
Una pila realizada con listas enlazadas crece y decrece dinmicamente.
En tiempo de ejecucin se reserva memoria segn se ponen los elementos en la
pila y se libera memoria segn se extraen elementos de la pila.
A diferencia de la cabecera de una lista usual, la cabecera de una pila no
va a ser un registro que incluya el nmero de nodos y punteros al primer y
ltimo elemento, sino que va a ser simplemente un puntero que apunta al primer
nodo.
La declaracin de la pila ser:

16

Elemento = E;
Nodo = registro de
info: elemento;
sgte: puntero a Nodo;
fin registro;
Pila = puntero a NODO.

Las operaciones principales sern las siguientes:

Crear_pila(PILA *P){
P->longitud=0;
P->prim=NULL;
}

/*Creaciones de la pila*/

Borrar_Pila (PILA *P){


while(!VACIA(P))
POP(P);
}

/*libera la pila*/

PUSH (PILA *P,elemento *x){


POSICION temp;
temp = crea_nodo(x);
temp->info=*x;
if(VACIA(P)){
P->prim=temp;
temp->sgte=NULL;
}
else{
temp->sgte=P->prim;
P->prim=temp;
}
P->longitud++;
}

/*Apila un elemento ms*/

POP (PILA *P){


/*Elimina el tope de la pila*/
NODE *q;
if (VACIA(P))
printf("No existe tope,ya que la pila est vaca.\n");
else {
q = P->prim;
P->prim = q->sgte;
free(q);
P->longitud--;
}
}

17

TOPE (PILA *P){


if (VACIA(P))
printf("No existe tope.\n");
else
return(P->prim->info);
}

/*Devuelve el elemento tope de la pila*/

PROGRAMA DEMO:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*Declaraciones*/
typedef int elemento;
struct NODE{
elemento info;
struct NODE *sgte;
};
typedef struct NODE nodo;
typedef NODE *POSICION;
typedef struct {
int longitud;
POSICION prim;
} PILA;

/*Creaciones de la pila*/
void crear_pila(PILA *P)
{
Plongitud=0;
Pprim=NULL;
}
/* Creacin de un nodo a partir de un elemento dado */
NODE * crea_nodo (elemento *i)
{
static NODE *p;
p = (NODE *) malloc (sizeof(NODE));
if (p == NULL)
printf ("\nError. No puedo crear puntero a estructura\n");
else{
pinfo= *i;
/* Copio datos originales, en campo info de nodo creado */
psgte = NULL;
}

18

Return (p);
}
/*la pila est vaca?*/
int VACIA (PILA *P)
{
int resp,tam;
tam = Plongitud;
resp = (tam == 0)?1:0;
return resp;
}
/*Devuelve el elemento tope de la pila*/
elemento TOPE (PILA *P)
{
if (VACIA(P))
printf ("No existe tope.\n");
else
return (P prim info);
}
/*Elimina el tope de la pila*/
void POP (PILA *P)
{
NODE *q;
if (VACIA (P) )
printf ("No existe tope,ya que la pila est vaca.\n" );
else {
q = Pprim;
Pprim = qsgte;
free(q);
Plongitud--;
}
}
/*libera la pila*/
void DESTRUIR (PILA *P)
{
While (!VACIA(P))
POP (P);
}
/*Apila un elemento ms*/
void PUSH (PILA *P,elemento *x)
{
POSICION temp;
temp = crea_nodo(x);
tempinfo =*x;

19

if(VACIA(P)){
P prim = temp;
Temp sgte = NULL;
}
else{
temp sgte = Pprim;
P prim = temp;
}
P longitud++;
}
/*Da la vuelta a la pila*/
PILA GIRA (PILA *P)
{
PILA S;
crear_pila (&S);
elemento r;
do{
r = TOPE (P);
PUSH (&S, &r);
POP (P);
}while (VACIA(P) == 0);
return S;
}
/*Mostrar el contenido de la pila*/
void contenido_pila(PILA *P)
{
PILA S;
elemento r;
crear_pila (&S);
S = GIRA (P);

/*Con dos pilas, muestra la pila inicial correctamente*/

printf("El contenido de la pila es:\n");


do{
r = TOPE (&S);
printf ("%d\n",r);
PUSH (P,&r);
POP (&S);
}while (VACIA(&S) == 0);
}

/* Empezamos nuestro programa principal en el utilizaremos todos los subprogramas anteriores,


cada uno para una cosa*/
main (){
PILA P,S;

20

FILE *in;
elemento x;
int opcion;
int resp;
char nombre[20];
char linea[10];
do{

/*Bucle do para que puedas realizar varias operaciones al mismo tiempo*/

printf("Elije una de las siguientes opciones:\n1. Crear una pila con los datos de un
fichero.\n2. Crear una pila con los datos por teclado.\n3. Guardar una pila en un fichero.\n4.
Borrar una pila.\n5. Insertar un elemento en una pila.\n6. Eliminar un elemento en una pila.\n7.
Mostrar el contenido de una pila.\n8. Terminar.\n");
scanf("%d",&opcion);
if (opcion == 1){
/*Abre un archivo, lee los datos y los mete en una pila*/
crear_pila (&P);
printf("dame el nombre del fichero del que sacar los datos(con extension .txt)");
scanf("%s",nombre);
if ((in = fopen(nombre, "r")) != NULL){
do{
fscanf (in,"%d",&x);
PUSH (&P,&x);
}while (fgets(linea,10,in) != NULL);
fclose(in);
}
else
printf ("No se pudo abrir el fichero ");
}
if (opcion == 2){
/*Crea una pila mediante los datos que le das por teclado*/
crear_pila(&P);
do{

/*El usuario elige cuantos datos quiere darle a la pila*/


printf ("\nQuieres introducir un elemento?(s=1/n=2)");
scanf ("%d",&resp);
if (resp == 1){
printf ("\nDame el elemento que quieres introducir");
scanf ("%d", &x);
PUSH (&P, &x);
}
}while(resp==1);
}
if (opcion == 3){
/*Dada una pila la gira, para que al meterla este en orden*/
crear_pila(&S);
S = GIRA(&P);
printf("Dame el nombre del fichero en que quieres guardar la pila(con
extension.txt)");
scanf("%s",nombre);
if((in = fopen(nombre, "w")) != NULL){ /*Abre un fichero y guardara la pila*/

21

do{
fprintf(in,"%d\n",TOPE(&S));
POP (&S);
Resp = VACIA(&S);
}while (resp==0);
}
else
printf("No se pudo abrir el fichero");
}
if (opcion == 4){
DESTRUIR (&P);
}

/*Elimina la pila*/

if (opcion == 5){
/*En esta funcin mete un elemento a la pila*/
printf("\nDame el elemento que quieres introducir");
scanf("%d", &x);
PUSH (&P, &x);
}
if (opcion == 6){
POP (&P);
}

/*En este otro caso saca un elemento de la pila*/

if (opcion == 7){
contenido_pila (&P);
}

/*Muestra los datos de la pila por pantalla*/

}while(opcion!=8);
}

REFERENCIAS:
Libros:
9
9
9
9

Estructuras de datos y algoritmos. Mark Allen Weiss


Estructuras de datos. Aho, Hopcroft, Ullman
Estructuras de datos. Cairo, Guardati
Fundamentos de programacin. Algoritmos, estructurasde datos. Una
perspectiva en C. Joyanes Aguilar
9 Fundamentos de programacin. Algoritmos, estructurasde datos y objetos.
Joyanes Aguilar

Paginas web:
9 www.fcad.uner.edu.ar/C_LicSistemas/
Materias/est_datos/MartinezQuiroga_06PilasyFilas.pdf -

9 www.politeca.ing.ula.ve/Contenido/Digiteca/ProyectosTesisGrado/Pregrado/Uni
versidaddelosAndes/IngenieriaSistemas/DepartamentoComputacion/2005/Rodri
guezJose.pdf

22

Vous aimerez peut-être aussi