Tipo de datos abstracto Pila a void II

Tipo de datos abstracto Pila a void II

Continuando con el tema que iniciamos ayer, hoy me dedicaré a dejaros una propuesta de los procedimientos constructor, destructor y una función auxiliar que comprueba si la pila está o no vacía. Como vamos a comprobar, ésta éstructura es un poco más compleja que la anterior.

Lo primero que vamos a hacer es escribir dos estructuras. La primera estará referida a cada uno de los nodos de la lista. Tendrá como campos un puntero a void que contendrá el tipo de dato que vamos a usar, y un puntero al nodo siguiente de la pila.

struct p_ele {
	void* val;
	struct p_ele* sig;
}

La segunda estructura, contendrá dos campos: el tamaño de los datos que vamos a almacenar en la pila y un puntero al primer elemento de la pila.

struct tpila {
	int tam;
	struct p_ele* p;
}

Comenzamos con la función constructor. Realmente es bastante fácil e intuitivo. Usaremos una variable local tpila que será la cabecera de la nueva estructura que estamos a punto de construir. Como siempre, reservamos memoria para la cabecera, comprobando si hay memoria o, por el contrario, habrá que salir del procedimiento con un mensaje de error. En caso de que todo haya ido bien, tan sólo tenemos que actualizar los campos de la estructura y devolver la nueva pila. ¿Fácil no?.

pila p_nueva ( int tam ) {

	struct tpila* nueva;
	
	nueva = (struct tpila* ) malloc ( sizeof ( struct tpila ) );
	if ( !nueva ) {
		fprintf ( stderr, "p_nueva: No hay suficiente memoria\n" );
		exit (1);
	}
	
	nueva->tam = tam;
	nueva->p = NULL;
	
	
	return nueva;

}

El procedimiento destructor, quizás, es un poquito más lioso, puesto que hay que hacer uso de muchos cast y, si te olvidas un paréntesis, te aparecerá algún mensaje de error. Por tanto, ten mucho cuidado cuando escribas el código.

void p_dest ( pila* p ) {

	struct p_ele* viejo;
	
	if ( !*p ) {
		fprintf ( stderr, "p_dest: La pila  no existe\n" );
		exit (1);
	}
	
	while ( ((struct tpila* )(*p))->p ) {
	
		viejo = ((struct tpila* ) (*p))->p;
		((struct tpila* ) (*p))->p = viejo->sig;
		free ( viejo->val );
		free ( viejo );
	
	}
	
	free ( *p );
	*p = NULL;
	
}

Obvio, lo primero que tendremos que hacer es verificar que la pila que pretendemos destruir efectívamente existe. Sino, pues no tiene caso seguir. Iniciaremos un bucle while que terminará cuando la pila apunte a NULL. Vamos a hacer uso de una variable auxiliar que almacene la dirección de memoria del puntero de la cabecera de la pila. A continuación eliminaremos el valor contenido en ese nodo. Seguidamente el nodo mismo.

Cuando hayamos terminado con todos los nodos de la pila, entonces eliminaremos la cabecerra de la pila e inicializaremos el puntero con el valor NULL. Con ésto, ya hemos terminado.

Nos queda, para terminar éste artículo, una pequeña función que nos permite saber mediante un booleano, si la pila está o no vacía.

int p_vacia ( pila p ) {

	if ( !p ) {
		fprintf ( stderr, "p_vacia: La pila  no existe\n" );
		exit (1);
	}
	
	return ((struct tpila*)p)->p == NULL;
	
}

Devuelve un valor entero. Comprobamos si la pila existe o no. En caso afirmativo, devolveremos el valor que tiene el puntero a la cabecera de la pila. Esto nos dirá si hay algún nodo almacenado o no.

Lo único que me queda por hacer en éste artículo es poner todo el código junto y, por supuesto, animar a mis lectores a que contribuyan con sus propias observaciones y código.

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

struct p_ele {
	void* val;
	struct p_ele* sig;
}

struct tpila {
	int tam;
	struct p_ele* p;
}


pila p_nueva ( int tam ) {

	struct tpila* nueva;
	
	nueva = (struct tpila* ) malloc ( sizeof ( struct tpila ) );
	if ( !nueva ) {
		fprintf ( stderr, "p_nueva: No hay suficiente memoria\n" );
		exit (1);
	}
	
	nueva->tam = tam;
	nueva->p = NULL;
	
	
	return nueva;

}


int p_vacia ( pila p ) {

	if ( !p ) {
		fprintf ( stderr, "p_vacia: La pila  no existe\n" );
		exit (1);
	}
	
	return ((struct tpila*)p)->p == NULL;
	
}

void p_dest ( pila* p ) {

	struct p_ele* viejo;
	
	if ( !*p ) {
		fprintf ( stderr, "p_dest: La pila  no existe\n" );
		exit (1);
	}
	
	while ( ((struct tpila* )(*p))->p ) {
	
		viejo = ((struct tpila* ) (*p))->p;
		((struct tpila* ) (*p))->p = viejo->sig;
		free ( viejo->val );
		free ( viejo );
	
	}
	
	free ( *p );
	*p = NULL;
	
}

Nos vemos en el siguiente artículo.

No Comments

Post a Comment