Kioskea
Recherche
Haz una pregunta »

Las pilas en lenguaje C

Febrero 2015


Las pilas





Requisitos


Los tipos de datos
Las estructuras
El uso de typedef
Los punteros
Las funciones de usuario
Las listas simplemente enlazadas
Las listas doblemente enlazadas

I. INTRUDUCCION


El objetivo de este articulo es que el lector comprenda el empleo de las pilas.
Para explicar el algoritmo he elegido utilizar una lista enlazada simple. Por lo tanto la comprensión de las listas enlazadas es necesaria.

II. Definición


La pila es una estructura de datos que permite almacenar datos en el orden LIFO (Last In First Out) en español, último en entrar, primero en salir).
La recuperación de los datos es hecha en el orden inverso de su inserción.

Para la implementación he elegido una lista enlazada simple, presentada sobre la vertical.
Ya que la inserción es siempre hecha al inicio de la lista, el 1er elemento de la lista será el ultimo elemento ingresado, por lo tanto estará en la cabeza de la pila.
No he utilizado un puntero fin, como lo hice en el caso de la lista enlazada simple, ya que el objetivo no es el de tratar una lista enlazada, sino una pila.
Lo interesante es que el ultimo elemento ingresado, será el 1er elemento recuperado.


III. La construcción del modelo de un elemento de la pila


Para definir un elemento de la pila será utilizado el tipo struct.
El elemento de la pila contendrá un campo dato y un puntero siguiente.
El puntero siguiente debe ser del mismo tipo que el elemento, de lo contrario no podrá apuntar hacia el elemento.
El puntero siguiente permitirá el acceso al próximo elemento.

typedef struct ElementoLista {
    char *dato;
    struct ElementoLista *siguiente;
}Elemento;


Para permitir las operaciones sobre la pila, vamos a guardar ciertos elementos:
  • el primer elemento
  • el numero de elementos


El 1er elemento, que se encuentra en la cabeza de la pila, nos permitirá realizar la operación de recuperación de los datos situados en la parte superior de la pila.

Para ello, será utilizada otra estructura (no es obligatorio, pueden ser utilizadas variables).

typedef struct ListaUbicación{
  Elemento *inicio;
  int tamaño;
} Pila;


El puntero inicio contendrá la dirección del 1er elemento de la lista.
La variable tamaño contiene el numero de elementos.

Nota:
Esta vez no utilizamos un puntero fin (ver la lista enlazada simple), no lo necesitamos puesto que únicamente trabajamos al inicio de la lista.

Cualquiera que sea la posición en la lista, el puntero inicio apunta siempre hacia el 1er elemento, que estará en la cabeza de la pila.
El campo tamaño contendrá el numero de elementos de la pila, cualquiera que sea la operación efectuada sobre la pila.

IV. Operaciones sobre las pilas


A. Inicialización


Modelo de la función:

void inicialización (Pila *tas);


Esta operación debe ser hecha antes de cualquier otra operación sobre la pila.
Esta inicializa el puntero inicio con el puntero NULL, y el tamaño con el valor 0.

La función

void inicialización (Pila * tas){
  tas->inicio = NULL;
  tas->tamaño = 0;
}

B. Inserción de un elemento en la pila


A continuación el algoritmo de inserción y registro de los elementos:
  • declaración del elemento a insertar
  • asignación de la memoria para el nuevo elemento
  • rellenar el contenido del campo de datos
  • actualizar el puntero inicio hacia el 1er elemento (la cabeza de la pila)
  • Actualizar el tamaño de la pila.


Modelo de la función:

int apilar (Pila *tas, char *dato);


La primera imagen muestra el inicio de la inserción, por lo tanto la lista de tamaño 1 después de la inserción. La característica de la pila no es muy apreciada con un solo elemento, ya que es el único a recuperar.



En cambio la 2da imagen nos permite observar el comportamiento de la pila.
Lo que debemos retener es que la inserción siempre se hace en la parte superior de la pila (al inicio de la lista).



La función

/* apilar (añadir) un elemento en la pila */
int apilar (Pila * tas, char *dato){
  Elemento *nuevo_elemento;
  if ((nuevo_elemento = (Elemento *) malloc (sizeof (Elemento))) == NULL)
    return -1;
  if ((nuevo_elemento->dato = (char *) malloc (50 * sizeof (char)))
      == NULL)
    return -1;
  strcpy (nuevo_elemento->dato, dato);
  nuevo_elemento->siguiente = tas->inicio;
  tas->inicio = nuevo_elemento;
  tas->tamaño++;
}

C. Eliminar un elemento de la pila


Para eliminar un elemento de la pila, simplemente hay que eliminar el elemento hacia el cual apunta el puntero inicio.
Esta operación no permite recuperar el dato en la cabeza de la pila, solo eliminarlo.

Modelo de la función:

int desapilar (Pila *tas);


La función devuelve -1 en caso de error, si no devuelve 0.

Las etapas:
  • el puntero sup_elemento contendrá la dirección del 1er elemento
  • el puntero inicio apuntará hacia el 2do elemento (después de la eliminación del 1er elemento, el 2do elemento estará en la cabeza de la pila)
  • el tamaño de la pila disminuirá un elemento.




La función

int desapilar (Pila * tas){
  Elemento *sup_elemento;
  if (tas->tamaño == 0)
    return -1;
  sup_elemento = tas->inicio;
  tas->inicio = tas->inicio->siguiente;
  free (sup_elemento->dato);
  free (sup_elemento);
  tas->tamaño--;
  return 0;
}

D. Visualización de la pila


Para mostrar la pila entera, es necesario posicionarse al inicio de la pila (el puntero inicio lo permitirá).
Luego, utilizando el puntero siguiente de cada elemento, la pila es recorrida del 1er hacia el ultimo elemento.
La condición para detenerse es dada por el tamaño de la pila.

La función

/* visualización de la pila */
void muestra (Pila * tas){
  Elemento *actual;
  int i;
  actual = tas->inicio;

  for(i=0;i<tas->tamaño;++i){
    printf("\t\t%s\n", actual->dato);
    actual = actual->siguiente;
  }
}

E. Recuperación del dato en la cabeza de la pila


Para recuperar el dato en la cabeza de la pila sin eliminarlo, he utilizado una macro. La macro lee los datos en la parte superior de la pila utilizando el puntero inicio.

#define pila_dato(tas)  tas->inicio->dato

V. Ejemplo completo


pila.h


/*********************\

 *      pila.h       *
\*********************/
typedef struct ElementoLista{
  char *dato;
  struct ElementoLista *siguiente;
} Elemento;

typedef struct ListaUbicación{
  Elemento *inicio;
  int tamaño;
} Pila;


/* inicialización */
void inicialización (Pila *tas);

/* APILAR*/
int apilar (Pile *tas, char *dato);

/* DESAPILAR*/
int desapilar (Pila *tas);

/* Visualización del elemento en la cabeza de la pila (LastInFirstOut) */
#define pila_dato(tas)  tas->inicio->dato

/* muestra la pila */
void muestra (Pila *tas);

pila_function.h


/***********************\

* pila_function.h     *
\***********************/

void inicialización (Pila * tas){
  tas->inicio = NULL;
  tas->tamaño = 0;
}

/* apilar (añadir) un elemento en la pila */
int apilar (Pila * tas, char *dato){
  Elemento *nuevo_elemento;
  if ((nuevo_elemento = (Elemento *) malloc (sizeof (Elemento))) == NULL)
    return -1;
  if ((nuevo_elemento->dato = (char *) malloc (50 * sizeof (char)))
      == NULL)
    return -1;
  strcpy (nuevo_elemento->dato, dato);
  nuevo_elemento->siguiente = tas->inicio;
  tas->inicio = nuevo_elemento;
  tas->tamaño++;
}

/* desapilar (eliminar un elemento de la pila */
int desapilar (Pila * tas){
  Elemento *sup_elemento;
  if (tas->tamaño == 0)
    return -1;
  sup_elemento = tas->inicio;
  tas->inicio = tas->inicio->siguiente;
  free (sup_elemento->dato);
  free (sup_elemento);
  tas->tamaño--;
  return 0;
}

/* visualización de la pila */
void muestra (Pila * tas){
  Elemento *actual;
  int i;
  actual = tas->inicio;

  for(i=0;i<tas->tamaño;++i){
    printf("\t\t%s\n", actual->dato);
    actual = actual->siguiente;
  }
}

pila.c


/*********************\

 *      pila.c       *
\*********************/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include "pila.h"
#include "pila_function.h"

int main ()
{
  Pila *tas;
  char *nom;
  if ((tas = (Pila *) malloc (sizeof (Pila))) == NULL)
    return -1;
  if ((nom = (char *) malloc (50 * sizeof (char))) == NULL)
    return -1;
  inicialización (tas);

  printf ("Ingrese una palabra: ");
  scanf ("%s", nom);
  apilar (tas, nom);
  printf ("La pila (%de elementos): \n",tas->tamaño);
  printf("\n********** Cabeza de la PILA **********\n");
  muestra(tas);
  printf("__________ Bajo de la PILA __________\n\n");

  printf ("Ingrese una palabra: ");
  scanf ("%s", nom);
  apilar (tas, nom);
  printf ("La pila (%de elementos): \n",tas->tamaño);
  printf("\n********** Cabeza de la PILA **********\n");
  muestra(tas);
  printf("__________ Bajo de la PILA __________\n\n");

  printf ("Ingrese una palabra: ");
  scanf ("%s", nom);
  apilar (tas, nom);
  printf ("La pila (%de elementos): \n",tas->tamaño);
  printf("\n********** Cabeza de la PILA **********\n");
  muestra(tas);
  printf("__________ Bajo de la PILA __________\n\n");

  printf ("\nLa ultima entrada (LastInFirstOut) [ %s ] sera eliminada",
                  pile_dato(tas));
  printf ("\nLa ultima entrada es eliminada\n");
  desapilar (tas);              /* eliminación del ultimo elemento ingresado */
  printf ("La pila (%de elementos): \n",tas->tamaño);
  printf("\n********** Cabeza de la PILA **********\n");
  muestra(tas);
  printf("__________ Bajo de la PILA __________\n\n");

  return 0;
}

VI. Ver también



PD: El artículo original fue escrito por lami20j, contribuidor de CommentCaMarche
Consulta este artículo sin tener que estar conectado, descárgalo gratis aquí en formato PDF:
Las-pilas-en-lenguaje-c.pdf

Consulta también

En la misma categoría

Les piles en langage C
Por lami20j el 7 de diciembre de 2007
As pilhas em linguagem C
Por pintuda el 26 de octubre de 2011
El artículo original fue escrito por lami20j. Traducido por Carlos-vialfa.
Este documento intitulado « Las pilas en lenguaje C » de Kioskea (es.kioskea.net) esta puesto a diposición bajo la licencia Creative Commons. Puede copiar, modificar bajo las condiciones puestas por la licencia, siempre que esta nota sea visible.