Desarrollo de una pila de enteros en C

Desarrollo de una pila de enteros en C

Rescato, en esta ocasión, una de las estructura de datos más sencillas que recuerdo de mi época universitaria. Quiero compartir un ejemplo sencillo de una pila que almacena números enteros -se puede adaptar a cualquier otro tipo de variable-.

Puedes descargarte, sin problemas, los ficheros necesarios desde mi cuenta personal de github.

Cabecera de las funciones y procedimientos del tipo de datos abstracto pila de enteros

#ifndef PILA_INT_TYPO

#define PILA_INT_TYPO

struct pila_int_typo   {
       int x;
   };

typedef struct pila_int_cabec *pila_int;

pila_int pila_int_init (void);
int pila_int_empty (pila_int p);
void pila_int_push (pila_int p, struct pila_int_typo *n);
void pila_int_pop (pila_int p, struct pila_int_typo *n);
pila_int pila_int_copy (pila_int p);
void pila_int_look (pila_int p, struct pila_int_typo *n);
void pila_int_delete (pila_int *p);

#endif

Implementación de las funciones y procedimientos

#include <stdio.h>
#include <stdlib.h>
#include <alloc.h>
#include "pila_int.h"

struct pila_int_cabec   {
	struct pila_int_ele *punt;
    };

struct pila_int_ele   {
	struct pila_int_typo val;
	struct pila_int_ele *sig;
    };

// ----------------------------------------------------------------------
//		  	FUNCIONES PRIVADAS
// ----------------------------------------------------------------------

void pila_int_error (int error, char *prim)    {
	switch (error)   {
	     case 1: fprintf (stderr, "\n\n\t%s: No hay suficiente memoria.\n", prim);
		     break;
	     case 2: fprintf (stderr, "\n\n\t%s: La pila no existe.\n", prim);
		     break;
	     case 3: fprintf (stderr, "\n\n\t%s: La pila esta vacia.\n", prim);
		     break;
	  }
   }
// ----------------------------------------------------------------------
//			FUNCIONES PUBLICAS
// ----------------------------------------------------------------------

pila_int pila_int_init ()     {
	pila_int nueva;

	nueva = (struct pila_int_cabec *) malloc (sizeof (struct pila_int_cabec));
	if (!nueva)    {
		pila_int_error (1, "pila_int_init");
		exit (-1);
	   }
	nueva -> punt = NULL;
	return (nueva);
   }
// ----------------------------------------------------------------------

int pila_int_empty (pila_int p)    {
	if (!p)   {
		pila_int_error (2, "pila_int_empty");
		exit (-1);
	   }
	return (p -> punt == NULL);
    }
// ----------------------------------------------------------------------

void pila_int_push (pila_int p, struct pila_int_typo *n)    {
	struct pila_int_ele *nuevo;

	if (!p)    {
		pila_int_error (2, "pila_int_push");
		exit (-1);
	   }
	nuevo = (struct pila_int_ele *) malloc (sizeof (struct pila_int_ele));
	if (!nuevo)   {
		pila_int_error (1, "pila_int_push");
		exit (-1);
	   }
	nuevo -> val = *n;
	if (pila_int_empty (p))   nuevo -> sig = NULL;
	else  nuevo -> sig = p -> punt;
	p -> punt = nuevo;
   }
// ----------------------------------------------------------------------

void pila_int_pop (pila_int p, struct pila_int_typo *n)    {
	struct pila_int_ele *viejo;

	if (!p)    {
		pila_int_error (2, "pila_int_pop");
		exit (-1);
	   }
	if (pila_int_empty (p))    {
		pila_int_error (3, "pila_int_pop");
		exit (-1);
	   }
	viejo = p -> punt;
	*n = viejo -> val;
	if (viejo -> sig == NULL)   p -> punt = NULL;
	else  p -> punt = viejo -> sig;
	free (viejo);
   }
// ----------------------------------------------------------------------

pila_int pila_int_copy (pila_int p)    {
	pila_int res;
	struct pila_int_ele *nuevo, *corr1, *corr2;

	if (!p)    {
		pila_int_error (2, "pila_int_copy");
		exit (-1);
	   }
	res = (struct pila_int_cabec *) malloc (sizeof (struct pila_int_cabec));
	if (!res)    {
		pila_int_error (1, "pila_int_copy");
		exit (-1);
	   }
	res -> punt = NULL;
	corr1 = p -> punt;
	while (corr1)   {
	      nuevo = (struct pila_int_ele *) malloc (sizeof (struct pila_int_ele));
	      if (!nuevo)   {
		    pila_int_error (1, "pila_int_copy");
		    exit (-1);
		 }
	      nuevo -> val = corr1 -> val;
	      nuevo -> sig = NULL;
	      if (pila_int_empty (res))    {
		    res -> punt = nuevo;
		    corr2 = nuevo;
		}
	      else  {
		    corr2 -> sig = nuevo;
		    corr2 = corr2 -> sig;
		}
	      corr1 = corr1 -> sig;
	  }
	return (res);
   }
// ----------------------------------------------------------------------

void pila_int_look (pila_int p, struct pila_int_typo *n)     {
	if (!p)    {
		pila_int_error (2, "pila_int_look");
		exit (-1);
	   }
	if (pila_int_empty (p))    {
		pila_int_error (3, "pila_int_look");
		exit (-1);
	   }
	*n = p -> punt -> val;
   }
// ----------------------------------------------------------------------

void pila_int_delete (pila_int *p)   {
	struct pila_int_ele *viejo;

	if (!*p)    {
		pila_int_error (2, "pila_int_delete");
		exit (-1);
	   }
	while (!pila_int_empty (*p))    {
		viejo = (*p) -> punt;
		(*p) -> punt = viejo -> sig;
		free (viejo);
	   }
	free (*p);
	*p = NULL;
   }

Programa de prueba

Te voy a dejar dos versiones de programas de prueba con la que probar la bondad y funcionalidades de éste tipo de dato abstracto. La primera versión es la siguiente:

#include <stdio.h>
#include <stdlib.h>
#include "pila_int.h"

// -----------------------------------------------------------------------
// 		PRIMITIVA QUE CALCULA EL FIBONACCI DE UN NUMERO
// -----------------------------------------------------------------------

unsigned long Fibonacci (int num)     {
     pila_int res;
     struct pila_int_typo n;
     unsigned long fib = 0;

     if (num < 0)   {
	   fprintf (stderr, "\n Fibonacci: El fibonacci de un numero negativo no existe.\n");
	   exit (-1);
	}

     res = pila_int_init ();
     n.x = num;
     pila_int_push (res, &amp;n);
     while (!pila_int_empty (res))    {
	   pila_int_pop (res, &amp;n);
	   if ((n.x == 0) || (n.x == 1))   fib += n.x;
	   else    {
		n.x = n.x--;      pila_int_push (res, &amp;n);
		n.x = n.x--;      pila_int_push (res, &amp;n);
	     }
       }

     pila_int_delete (&amp;res);
     return (fib);
   }

// -----------------------------------------------------------------------

void main (int argc, char *argv[])   {
	int i, num;
	unsigned long fib;
	if (argc < 2)    {
		printf ("\n ERROR (Fibonacc): La ejecucion del progama se debe hacer de la forma:\n");
		printf ("\t fibonacc <n1> <n2> ... <nn>");
		exit (1);
	   }

	for (i = 1; i < argc; i++)   {
		num = atoi (argv [i]);
		fib = Fibonacci (num);
		printf ("\n Fibonacci (%d) = %lu" ,num, fib);
	   }
  }

La segunda versión de la versión del programa de prueba de la muestro a continuación:

#include <stdio.h>
#include <conio.h>
#include "pila_int.h"

// -----------------------------------------------------------------------
// 		PRIMITIVA QUE CALCULA EL FIBONACCI DE UN NUMERO
// -----------------------------------------------------------------------

int Fibonacci (int num)     {
     pila_int res;
     struct pila_int_typo n;
     int fib = 0;

     res = pila_int_init ();
     n.x = num;
     pila_int_push (res, &amp;n);
     while (!pila_int_empty (res))    {
	   pila_int_pop (res, &amp;n);
	   if ((n.x == 0) || (n.x == 1))   fib += n.x;
	   else    {
		n.x = n.x--;      pila_int_push (res, &amp;n);
		n.x = n.x--;      pila_int_push (res, &amp;n);
	     }
       }

     pila_int_delete (&amp;res);
     return (fib);
   }
// -----------------------------------------------------------------------

void main ()   {
    char opc, fin, seguir = 's';
    pila_int a = NULL, b = NULL;
    struct pila_int_typo n;
    int i, f;

    clrscr ();
    while (seguir == 's')   {

      printf ("\t MANEJO DE UNA PILA DINAMICA\n\n");
      printf ("\t a) Crear una pila vacia.\n");
      printf ("\t b) Introducir un elemento.\n");
      printf ("\t c) Sacar un elemento.\n");
      printf ("\t d) Mirar el elemento tope.\n");
      printf ("\t e) Realizar una copia.\n");
      printf ("\t f) Calcular la serie de Fibonacci.\n");
      printf ("\t s) Salir.\n");

      printf ("\n\t Introduzca la opcion a realizar: ");
      opc = getche ();
      switch (opc)    {
	    case 'a': a = pila_int_init ();
		      printf ("\n\n\t Operacion realizada...");
		      break;
	    case 'b': printf ("\n\n\t Introduzca el dato a guardar en la pila: ");
		      scanf ("%d", &amp;n.x);
		      pila_int_push (a, &amp;n);
		      break;
	    case 'c': pila_int_pop (a, &amp;n);
		      printf ("\n\n\t El primer elemento es el: %d", n.x);
		      break;
	    case 'd': pila_int_look (a, &amp;n);
		      printf ("\n\n\t El primer elemento de la pila A es el: %d", n.x);
		      pila_int_look (b, &amp;n);
		      printf ("\n\n\t El primer elemento de la pila B es el: %d", n.x);
		      break;
	    case 'e': b = pila_int_copy (a);
		      printf ("\n\n\t Operacion realizada...");
		      break;
	    case 'f': printf ("\n\n\t La serie de Fibonacci queda de la siguiente forma:\n\n\t ");
		      for (i = 0; i < 24; i++)   {
			     f = Fibonacci (i);
			     printf (" %d,", f);
			 }
		      printf (".....");
		      break;
	    case 's': seguir = 'n';
	 }
	printf ("\n\n\t Pulse una tecla para continuar.....");
	fin = getch ();
	clrscr ();
     }
    if (a) pila_int_delete (&amp;a);
    if (b) pila_int_delete (&amp;b);
  }

Conclusión

Te invito a que visites y compartas los artículos que escribo sobre programación de estructuras de datos lineales y no lineales en mi blog personal: lista genérica en c, arbol binario avl, árbol binario, ficheros dispersos o doble cola dinámica.

Pongo a vuestra disposición, también, la sección de contactos para que me dejéis vuestra impresiones, aportaciones o código alternativo. De ésta forma, compartiendo esta información serviremos al propósito de aprender todos.

No Comments

Post a Comment