<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>el blog de giltesa &#187; Software</title>
	<atom:link href="http://giltesa.com/category/informatica/software/feed/" rel="self" type="application/rss+xml" />
	<link>http://giltesa.com</link>
	<description></description>
	<lastBuildDate>Fri, 10 Feb 2012 00:44:42 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>6&#215;06: Bicolas en lenguaje C</title>
		<link>http://giltesa.com/2012/02/10/6x06-bicolas-en-lenguaje-c/</link>
		<comments>http://giltesa.com/2012/02/10/6x06-bicolas-en-lenguaje-c/#comments</comments>
		<pubDate>Fri, 10 Feb 2012 00:44:42 +0000</pubDate>
		<dc:creator>giltesa</dc:creator>
				<category><![CDATA[C]]></category>
		<category><![CDATA[Programación]]></category>

		<guid isPermaLink="false">http://giltesa.com/?p=8928</guid>
		<description><![CDATA[]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><a href="http://giltesa.com/wp-content/uploads/2012/02/bicolas.png"><img class="alignnone size-medium wp-image-8930" title="bicolas" src="http://giltesa.com/wp-content/uploads/2012/02/bicolas-323x270.png" alt="" width="323" height="270" /></a></p>
<p><span id="more-8928"></span></p>
<pre class="brush: cpp; title: ; notranslate">
/*
6x06-Uso_de_bicolas
09/02/2012

Una bicola es una estructura de datos dinámica, similar a una cola, pero en la que cada elemento apunta además de al siguiente,también al anterior. Es decir, está doblemente encadenada. Implementa una bicola con las siguientes operaciones:

	a. creaVacia: Crea una bicola vacía.
	b. agnadeIzq: Añade un elemento a la bicola por la izquierda.
	c. agnadeDer: Añade un elemento a la bicola por la derecha.
	d. eliminaIzq: Elimina un elemento de la bicola por la izquierda.
	e. eliminaDer: Elimina un elemento de la bicola por la derecha.
	f. observaIzq: Devuelve el elemento que hay más a la izquierda.
	g. observaDer: Devuelve el elemento que hay más a la derecha.
	h. esVacia: Indica si la bicola está o no vacía.
	i. long: Devuelve la longitud de la bicola.
	j. asigna: copia una bicola en otra.
	k. libera: Destruye una bicola liberando toda la memoria que ocupaba.
	l. iguales: Indica si dos bicolas son iguales o no, en cuanto a los elementos que contienen ambas exactamente en el mismo orden.
*/

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

struct INFO
{
	int num;
};

struct NODO
{
	struct INFO elemento;
	struct NODO *p_anterior;
	struct NODO *p_siguiente;
};

struct BICOLA
{
	int nodos;
	struct NODO *primero;
	struct NODO *ultimo;
};

/* FUNCIONES ******************************************************************/

// Pone los punteros de una bicola a NULL
void inicializarBicola( struct BICOLA **bicola )
{
	/*
	Precondición:
					Se recibe un doble puntero de tipo struct BICOLA a una Bicola sin inicializar..
	Poscondición:
					Se inicializa la Bicola poniéndola a NULL o 0 según el parámetro a inicializar.
	*/

	// Se solicita memoria al sistema para la nueva Bicola:
	struct BICOLA *temp = (struct BICOLA *) malloc(sizeof(struct BICOLA));

	temp-&gt;nodos		= 0;
	temp-&gt;primero	= NULL;
	temp-&gt;ultimo	= NULL;

	(*bicola) 		= temp;

};

// Inserta nodos por la izquierda:
void insertIzqBicola( struct BICOLA **bicola, int dato )
{
	/*
	Precondición:
					Se recibe un doble puntero de tipo struct BICOLA a una Bicola y un parámetro de tipo entero con el dato a introducir.
	Poscondición:
					Se inserta al principio un nuevo Nodo en la Bicola.
	*/

	// Se solicita memoria al sistema para el nuevo Nodo:
	struct NODO *temp = (struct NODO *) malloc(sizeof(struct NODO));

	// Si la Bicola no tiene Nodos se inserta sin mas
	if( (*bicola)-&gt;primero == NULL )
	{
		temp-&gt;elemento.num	= dato;					// Se guarda el nuevo dato en el nuevo Nodo.
		temp-&gt;p_anterior	= NULL;					// Como es el primer Nodo de la Bicola, tanto el puntero anterior como el siguiente apuntan a NULL.
		temp-&gt;p_siguiente	= NULL;

		(*bicola)-&gt;primero	= temp;					// Como es el primer Nodo de la Bicola, se hace que primero y ultimo apunten ambos al mismo Nodo.
		(*bicola)-&gt;ultimo	= temp;
	}
	else
	{
		temp-&gt;elemento.num	= dato;					// Se guarda el dato nuevo en el nuevo Nodo.
		temp-&gt;p_anterior	= NULL;					// Como el nuevo Nodo va a ser el primero de la Bicola no apuntara a ningún Nodo anterior.
		temp-&gt;p_siguiente	= (*bicola)-&gt;primero;	// El nuevo Nodo apuntara al siguiente Nodo (donde ahora apunta &quot;primero&quot;.

		(*bicola)-&gt;primero-&gt;p_anterior	= temp;		// El puntero anterior del primer Nodo se hace que apunte al nuevo Nodo.
		(*bicola)-&gt;primero				= temp;		// El puntero del primero se hace que apunte al nuevo Nodo que ahora es el primero.
	};

	(*bicola)-&gt;nodos += 1;							// Se suma 1 a la variable que guarda el numero de Nodos de la Bicola.

};

// Inserta nodos por la derecha:
void insertDerBicola( struct BICOLA **bicola, int dato )
{
	/*
	Precondición:
					Se recibe un doble puntero de tipo struct BICOLA a una Bicola y un parámetro de tipo entero con el dato a introducir.
	Poscondición:
					Se inserta al final un nuevo Nodo en la Bicola.
	*/

	struct NODO *temp = (struct NODO *) malloc(sizeof(struct NODO));

	// Si la bicola esta vacía se introduce sin mas:
	if( (*bicola)-&gt;primero == NULL )
	{
		temp-&gt;elemento.num	= dato;
		temp-&gt;p_anterior	= NULL;
		temp-&gt;p_siguiente	= NULL;

		(*bicola)-&gt;primero	= temp;
		(*bicola)-&gt;ultimo	= temp;
	}
	  // Si contiene nodos, se introduce al final de todos ellos:
	else
	{
		temp-&gt;elemento.num	= dato;
		temp-&gt;p_anterior	= (*bicola)-&gt;ultimo;
		temp-&gt;p_siguiente	= NULL;

		(*bicola)-&gt;ultimo-&gt;p_siguiente	= temp;
		(*bicola)-&gt;ultimo				= temp;
	};

	(*bicola)-&gt;nodos += 1;

};

// Elimina el primer Nodo:
void eliminaIzqBicola( struct BICOLA **bicola )
{
	/*
	Precondición:
					Se recibe un doble puntero de tipo struct BICOLA a una Bicola.
	Poscondición:
					Se elimina el primer Nodo de la Bicola.
	*/

	struct NODO *aBorrar;

	// Si la Bicola esta vacía...
	if( (*bicola)-&gt;primero == NULL )
	{
		printf( &quot;No puede eliminar Nodos de una Bicola vacía.&quot; );
	}
	  // Si solo hay un Nodo en la Bicola, al liberar la RAM del Nodo se inicializa la Bicola a los valores por defecto:
	else if( (*bicola)-&gt;nodos == 1 )
	{
		free(*bicola);
		inicializarBicola( bicola );
	}
	  // En caso contrario se elimina solo el primer Nodo:
	else if( (*bicola)-&gt;nodos &gt; 1 )
	{
		aBorrar = (*bicola)-&gt;primero;

		(*bicola)-&gt;primero-&gt;p_siguiente-&gt;p_anterior	= NULL;
		(*bicola)-&gt;primero							= (*bicola)-&gt;primero-&gt;p_siguiente;
		free(aBorrar);

		(*bicola)-&gt;nodos -= 1;
	};

};

// Elimina el ultimo Nodo:
void eliminaDerBicola( struct BICOLA **bicola )
{
	/*
	Precondición:
					Se recibe un doble puntero de tipo struct BICOLA a una Bicola.
	Poscondición:
					Se elimina el ultimo Nodo de la Bicola.
	*/

	struct NODO *aBorrar;

	// Si la Bicola esta vacia...
	if( (*bicola)-&gt;primero == NULL )
	{
		printf( &quot;No puede eliminar Nodos de una Bicola vacía.&quot; );
	}
	  // Si solo hay un Nodo en la Bicola, al liberar la RAM del Nodo se inicializa la Bicola a los valores por defecto:
	else if( (*bicola)-&gt;nodos == 1 )
	{
		free(*bicola);
		inicializarBicola( bicola );
	}
	else if( (*bicola)-&gt;nodos &gt; 1 )
	{
		aBorrar = (*bicola)-&gt;ultimo;

		(*bicola)-&gt;ultimo-&gt;p_anterior-&gt;p_siguiente	= NULL;
		(*bicola)-&gt;ultimo							= (*bicola)-&gt;ultimo-&gt;p_anterior;
		free(aBorrar);

		(*bicola)-&gt;nodos -= 1;
	};

};

// Devuelve un true o un false si la Bicola contiene o no Nodos:
int tieneNodosLaBicola( struct BICOLA **bicola )
{
	/*
	Precondición:
					Se recibe un doble puntero de tipo struct BICOLA a una Bicola.
	Poscondición:
					Se devuelve un parámetro de tipo entero con valores true 1 o false 0 dependiendo de si la Bicola contiene Nodos o no.
	*/

	int resp = 0;

	if( (*bicola)-&gt;nodos != 0 )
		resp = 1;

	return resp;
};

// Libera la memoria RAM usada por la Bicola:
void borraLaBicola( struct BICOLA **bicola )
{
	/*
	Precondición:
					Se recibe un doble puntero de tipo struct BICOLA a una Bicola.
	Poscondición:
					Se libera la RAM usada por los Nodos contenidos en la Bicola.
	*/

	struct NODO *actual, *siguiente;
	actual = (*bicola)-&gt;primero;

	while( actual != NULL )
	{
		siguiente = actual-&gt;p_siguiente;
		free(actual);
		actual = siguiente;
	};

	*bicola = NULL;
};

// Devuelve el número de Nodos que contiene la Bicola:
int cuantosNodosTieneLaBicola( struct BICOLA **bicola )
{
	/*
	Precondición:
					Se recibe un doble puntero de tipo struct BICOLA a una Bicola.
	Poscondición:
					Se devuelve un parámetro de tipo entero que indica el número de Nodos que contiene la Bicola.
	*/

	return (*bicola)-&gt;nodos;
};

// Copia la bicola original a la bicola copia:
void copiarLaBicola( struct BICOLA **bicolaA, struct BICOLA **bicolaB )
{
	/*
	Precondición:
					Se han de recibir dos dobles punteros de tipo struct BICOLA a dos Bicolas.
	Poscondición:
					Se copia íntegramente la BicolaA en la BicolaB
	*/

	struct NODO *temp = (struct NODO *) malloc(sizeof(struct NODO));
	temp = (*bicolaA)-&gt;primero;

	// Si la BicolaB no esta vacia, se libera la RAM antes de copiar la BicolaA en BicolaB.
	if( (*bicolaB)-&gt;primero != NULL )
	{
		borraLaBicola( bicolaB );		// Se borra y se inicializa.
		inicializarBicola( bicolaB );
	};

	if( temp == NULL )
		printf( &quot;La Bicola A no contiene Nodos, no se puede copiar nada.&quot; );
	else
	{
		while( temp != NULL )
		{
			// Se inserta al final:
			insertDerBicola( bicolaB, temp-&gt;elemento.num );

			// Se avanza un Nodo hacia delante:
			temp = temp-&gt;p_siguiente;
		};

	};

	free(temp);

};

// Compara dos bicolas, devuelve true o false
int sonIgualesLasBicolas( struct BICOLA **bicolaA, struct BICOLA **bicolaB )
{
	/*
	Precondición:
					Se han de recibir dos dobles punteros de tipo struct BICOLA a dos Bicolas.
	Poscondición:
					Se devuelve un true 1 si las dos Bicolas son idénticas. En caso de que haya alguna diferencia entre ellas, ya sea en el contenido de sus Nodos o en la longitud de las Bicolas se devolverá un false 0.
	*/

	struct NODO *bicA = (struct NODO *) malloc(sizeof(struct NODO));
	struct NODO *bicB = (struct NODO *) malloc(sizeof(struct NODO));
	int salirBucle=0, resp=1;

	bicA = (*bicolaA)-&gt;primero;
	bicB = (*bicolaB)-&gt;primero;

	if( bicA == NULL ||  bicB == NULL )
	{
		resp = 0;

		if( bicA == NULL )
			printf( &quot;Debe de insertar antes algún Nodo en la Bicola A\n&quot; );

		if( bicB == NULL )
			printf( &quot;Debe de insertar antes algún Nodo en la Bicola B\n&quot; );
	}
	else
	{
		while( !salirBucle )
		{
			// Si alguno de los datos (num en este caso) del elemento de cada Nodo de la Bicola es diferente de la copia, devuelve false:
			if( bicA-&gt;elemento.num != bicB-&gt;elemento.num )
			{
				resp = 0;
				salirBucle = 1;
			}
			 // Si todo es igual...
			else
			{
				// Si los dos punteros siguen a puntando a algo diferente de NULL se avanza una posición:
				bicA = bicA-&gt;p_siguiente;
				bicB = bicB-&gt;p_siguiente;

				// Si alguno de los dos punteros ha llegado a NULL antes que el otro, las Bicolas están mal copiadas:
				if( (bicA != NULL  &amp;&amp;  bicB == NULL)  ||  (bicA == NULL  &amp;&amp;  bicB != NULL) )
				{
					resp = 0;
					salirBucle = 1;
				}
				  // Si por el contrario, las dos están a NULL a la vez, se termina la iteración y se devuelve true;
				else if( (bicA == NULL  &amp;&amp;  bicB == NULL) )
				{
					salirBucle = 1;
				};

			};

		};

	};

	return resp;

};

// imprime por pantalla el contenido de todos los Nodos de la Bicola:
void imprimeBicola( struct BICOLA **bicola )
{
	/*
	Precondición:
					Se recibe un doble puntero de tipo struct BICOLA a una Bicola.
	Poscondición:
					Se imprime por pantalla el contenido de todos los Nodos.
	*/

	struct NODO *bic = (*bicola)-&gt;primero;

	if( bic == NULL )
		printf( &quot;La Bicola no contiene Nodos.&quot; );
	else
	{

		printf( &quot;Su Bicola contiene: &quot; );

		while( bic != NULL )
		{
			printf( &quot;%i, &quot;, bic-&gt;elemento.num );
			bic = bic-&gt;p_siguiente;
		};

		printf( &quot;\n\n&quot; );

	};

};

/****************************************************************** FUNCIONES */

/**************************************************************************************************************************/
main()
{
	enum opciones{ salir, insertIzq, insertDer, eliminaIzq, eliminaDer, impIzq, impDer, impTodos, quedanNodos, cuantosNodosHay, copiaBicola, sonBicolasIguales, borraBicola } opc;
	struct BICOLA *bicolaA;
	struct BICOLA *bicolaB;
	int eleccion, nuevoDato;

	// Se inicializan las dos Bicolas poniéndolas a NULL:
	inicializarBicola( &amp;bicolaA );
	inicializarBicola( &amp;bicolaB );

	// Menú de selección:
	do{
		printf( &quot;\n\n&quot; );
		printf( &quot;Indique que desea hacer con los Nodos de la Bicola:\n\n&quot; );
		printf( &quot;   1. Añadir un Nodo por la izquierda\n&quot; );
		printf( &quot;   2. Añadir un Nodo por la derecha\n&quot; );
		printf( &quot;   3. Eliminar el primer Nodo\n&quot; );
		printf( &quot;   4. Eliminar el ultimo Nodo\n&quot; );
		printf( &quot;   5. Mostrar el primer Nodo\n&quot; );
		printf( &quot;   6. Mostrar el ultimo Nodo\n&quot; );
		printf( &quot;   7. Muestra todos los Nodos\n&quot; );
		printf( &quot;   8. Quedan Nodos?\n&quot; );
		printf( &quot;   9. Cuantos Nodos hay?\n&quot; );
		printf( &quot;  10. Copiar BicolaA a una nueva BicolaB\n&quot; );
		printf( &quot;  11. BicolaA es igual que BicolaB?\n&quot; );
		printf( &quot;  12. Borrar la BicolaA\n\n&quot; );
		printf( &quot;   0. Salir del programa.\n&quot; );

		do{
			scanf( &quot;%i&quot;, &amp;eleccion );
		} while( eleccion &lt; 0  &amp;&amp;  eleccion &gt; 12 );
		opc = (enum opciones)(eleccion);

		printf( &quot;\n\n&quot; );

		switch( opc )
		{

			case insertIzq:
				printf( &quot;Introduzca el número entero que contendrá el nuevo Nodo de la Bicola: &quot; );
				scanf( &quot;%i&quot;, &amp;nuevoDato );
				insertIzqBicola( &amp;bicolaA, nuevoDato );
			break;

			case insertDer:
				printf( &quot;Introduzca el número entero que contendrá el nuevo Nodo de la Bicola: &quot; );
				scanf( &quot;%i&quot;, &amp;nuevoDato );
				insertDerBicola( &amp;bicolaA, nuevoDato);
			break;

			case eliminaIzq:
				eliminaIzqBicola( &amp;bicolaA );
			break;

			case eliminaDer:
				eliminaDerBicola( &amp;bicolaA );
			break;

			case impIzq:
				if( tieneNodosLaBicola( &amp;bicolaA ) )
					printf( &quot;El primer Nodo contiene un: %i\n&quot;, bicolaA-&gt;primero-&gt;elemento.num );
				else
					printf(&quot;La Bicola no contiene Nodos&quot;);
			break;

			case impDer:
				if( tieneNodosLaBicola( &amp;bicolaA ) )
					printf( &quot;El ultimo Nodo contiene un: %i\n&quot;, bicolaA-&gt;ultimo-&gt;elemento.num );
				else
					printf(&quot;La Bicola no contiene Nodos&quot;);
			break;

			case impTodos:
				imprimeBicola( &amp;bicolaA );
			break;

			case quedanNodos:
				if( tieneNodosLaBicola( &amp;bicolaA ) )
					printf( &quot;La Bicola contiene Nodos.&quot; );
				else
					printf( &quot;La Bicola esta vacía.&quot; );

			break;

			case cuantosNodosHay:
				printf( &quot;La Bicola contiene %i Nodos.&quot;,  cuantosNodosTieneLaBicola( &amp;bicolaA ) );
			break;

			case copiaBicola:
				copiarLaBicola( &amp;bicolaA, &amp;bicolaB );
			break;

			case sonBicolasIguales:
				if( sonIgualesLasBicolas( &amp;bicolaA, &amp;bicolaB ) )
					printf( &quot;Las Bicolas son idénticas&quot; );
				else
					printf( &quot;Las Bicolas son diferentes&quot; );
			break;

			case borraBicola:
				borraLaBicola( &amp;bicolaA );		// Se borran todos los nodos...
				inicializarBicola( &amp;bicolaA );	// ... y después se inicializa.
			break;

			case salir:
				system(&quot;clear&quot;);
			break;

		};

	} while( opc != salir );

	// Libera la RAM que pudiera quedar sin liberar:
	borraLaBicola( &amp;bicolaA );
	borraLaBicola( &amp;bicolaB );

};
</pre>
]]></content:encoded>
			<wfw:commentRss>http://giltesa.com/2012/02/10/6x06-bicolas-en-lenguaje-c/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>6×05: Torres de Hanoi con pilas</title>
		<link>http://giltesa.com/2012/02/09/6%c3%9705-torres-de-hanoi-con-pilas/</link>
		<comments>http://giltesa.com/2012/02/09/6%c3%9705-torres-de-hanoi-con-pilas/#comments</comments>
		<pubDate>Thu, 09 Feb 2012 00:12:51 +0000</pubDate>
		<dc:creator>giltesa</dc:creator>
				<category><![CDATA[C]]></category>
		<category><![CDATA[Programación]]></category>

		<guid isPermaLink="false">http://giltesa.com/?p=8919</guid>
		<description><![CDATA[]]></description>
			<content:encoded><![CDATA[<div id="attachment_8808" class="wp-caption aligncenter" style="width: 480px"><a href="http://giltesa.com/?p=8807"><img class="size-medium wp-image-8808 " title="hanoi2" src="http://giltesa.com/wp-content/uploads/2012/01/hanoi2-470x89.png" alt="Hanoi con pilas C" width="470" height="89" /></a><p class="wp-caption-text">Mismo ejercicio que el 5×07 pero con pilas.</p></div>
<p><span id="more-8919"></span></p>
<pre class="brush: cpp; title: ; notranslate">
/*
6x05-Hanoi_con_pilas
08/02/2012

Implementa el ejercicio de las torres de Hanoi, utilizando pilas para representar las torres.
*/

#include
#include

struct DISCO
{
	int ancho;	// Contendrá el ancho, en intervalos impares, del disco.
	int altura;	// Contiene el nivel en el que se encuentra ese disco.
};

struct NODO
{
	struct DISCO disc;
	struct NODO *puntero;
};

// FUNCIÓN QUE INTRODUCE UN NUMERO EN UNA PILA:
void insertaDatoEnLaPila( struct NODO **pila, int disco )
{
	/*
	Precondición:
					Se ha de recibir un doble puntero de tipo struct NODO para una pila, y un parámetro de tipo entero.
	Poscondición:
					Se introduce el número recibido en la pila.
	*/

	// Se crea un puntero y se le asigna la dirección a la memoria necesaria para un nodo:
	struct NODO *temp = (struct NODO *) malloc(sizeof(struct NODO));

	// Si la pila no tiene nodos (NULL) la altura del disco que se va a introducir sera siempre de 1. Sin embargo si ya tiene nodos, la altura sera igual a la del nodo inferior +1.
	if( *pila == NULL )
		temp-&gt;disc.altura = 1;
	else
		temp-&gt;disc.altura = (*pila)-&gt;disc.altura + 1;

	temp-&gt;disc.ancho = disco;
	temp-&gt;puntero	 = *pila;
	*pila			 = temp;

};

// FUNCIÓN QUE EXTRAE EL PRIMER ELEMENTO DE LA PILA Y BORRA EL NODO VACIO:
int extraeDatoDeLaPila( struct NODO **pila, int *numNivel )
{
	/*
	Precondición:
					Se ha de recibir un doble puntero de tipo struct NODO para una pila.
					También un parámetro por referencia de tipo entero en el cual se guardara la altura en el que se encuentra el disco.
						Ese dato en el caso de la función mueveDisco() no sirve para nada, sin embargo es necesario desde la función imprimeTablero();
						Si la pila resultase NULL se devolverá, o mejor dicho, no se modificara el valor original que debería de ser 0.
	Poscondición:
					Se devuelve el primer parámetro de tipo entero almacenado en la pila, si esta vacía devuelve un 0.
					Devuelve por referencia la altura del disco.
	*/

	struct NODO *siguiente;
	int resp;

	if( *pila == NULL )
		resp = 0;
	else
	{
		// Se copia el ancho a la variable que va a ser retornada por la función:
		*numNivel	= (*pila)-&gt;disc.altura;
		resp		= (*pila)-&gt;disc.ancho;

		// Se elimina el primer Nodo (el vaciado):
		siguiente = (*pila)-&gt;puntero;
		free(*pila);
		*pila = siguiente;
	};

	return resp;
};

// FUNCIÓN QUE CREA UNA COPIA IDENTICA DE UNA PILA:
void creaUnaCopiaDePila( struct NODO **pila, struct NODO **pilaCopia )
{
	/*
	Precondición:
					Se reciben dos dobles punteros a dos pilas de tipo struct NODO, la primera ha de tener nodos y la segunda ha de estar vacía.
	Poscondición:
					Se realiza una copia exacta de toda la pila de la original a la copia.
	*/

	struct NODO *siguiente = *pila;
	struct NODO *antBusq;
	struct NODO *sigBusq;
	struct NODO *temp;

	// Mientras el puntero siguiente siga apuntando a otro Nodo...
	while( siguiente != NULL )
	{

		temp = (struct NODO *) malloc(sizeof(struct NODO));

		// Si la pila nueva no tiene ningún Nodo se introduce al principio:
		if( *pilaCopia == NULL )
		{
			temp-&gt;disc 		= siguiente-&gt;disc;
			temp-&gt;puntero	= NULL;
			*pilaCopia		= temp;
		}
		  // En caso contrario se introducen los siguientes Nodos siempre al final de la pila (que se esta tratando como una cola).
		else
		{
			sigBusq = *pilaCopia;

			// Se busca el ultimo Nodo:
			while( sigBusq != NULL )
			{
				antBusq = sigBusq;
				sigBusq = sigBusq-&gt;puntero;
			};

			temp-&gt;disc 		 = siguiente-&gt;disc;
			temp-&gt;puntero	 = NULL;
			antBusq-&gt;puntero = temp;
		};

		// Se avanza una posición en el puntero de la lista original:
		siguiente = siguiente-&gt;puntero;
	};

};

// FUNCIÓN QUE BORRA UNA LISTA ENTERA:
void borrarLista( struct NODO **lista )
{
	/*
	Precondición:
					Se ha de recibir un puntero de tipo struct NODO al primer nodo de la lista.
	Poscondición:
					Se borran todos los nodos de esa lista hasta llegar a NULL.
	*/

	struct NODO *actual, *siguiente;
	actual = *lista;

	while(actual != NULL)
	{
		siguiente = actual-&gt;puntero;
		free(actual);
		actual = siguiente;
	};

	*lista = NULL;

};

// FUNCIÓN QUE IMPRIME EL TABLERO DE HANOI:
void imprimeTablero( struct NODO **pilaO, struct NODO **pilaA, struct NODO **pilaD, int totDiscos, int tamDiscGrande )
{
	/*
	Precondición:
					pilaO, pilaA, pilaD			Se reciben tres dobles punteros a tres pilas de tipo struct NODO.
					totDiscos					Parámetro de tipo entero que indica el numero de discos totales para calcular el tiempo de pausa por cada impresión.
					tamDiscGrande				Parámetro de tipo entero que indica el tamaño del disco mas grande, se emplea para calcular los espacios a imprimir a ambos lados del disco.
*/

	// Se crean tres punteros temporales:
	struct NODO *pilaOc=NULL, *pilaAc=NULL, *pilaDc=NULL;

	int discoO, discoA, discoD, nivelO=0, nivelA=0, nivelD=0;
	int espO, espA, espD;
	int numNivel;
	int i;

	// Se usan los punteros temporales para que apunten a unas nuevas pilas idénticas a las originales:
	creaUnaCopiaDePila( pilaO, &amp;pilaOc );
	creaUnaCopiaDePila( pilaA, &amp;pilaAc );
	creaUnaCopiaDePila( pilaD, &amp;pilaDc );

	// Se obtiene el numero de disco por return y la altura del disco por referencia...
	discoO = extraeDatoDeLaPila(&amp;pilaOc, &amp;nivelO);
	discoA = extraeDatoDeLaPila(&amp;pilaAc, &amp;nivelA);
	discoD = extraeDatoDeLaPila(&amp;pilaDc, &amp;nivelD);

	// Se recorren todos los niveles de las pilas aunque estén vacíos:
	for( numNivel=totDiscos; numNivel &gt; 0; numNivel-- )
	{

		// Se calculan los espacios necesarios para el disco a imprimir en la altura correspondiente:
		espO = ( tamDiscGrande - discoO )/2;
		espA = ( tamDiscGrande - discoA )/2;
		espD = ( tamDiscGrande - discoD )/2;

		// Si la altura en la que se esta, la marca el for, es la misma que la altura del disco que se ha leído... se imprime, en caso contrario se imprimen tantos espacios como ancho tenga el disco mas grande.
		// Torre 1 o Origen:
		if( nivelO == numNivel )
		{
			// Espacios a la izquierda
			for( i=0; i &lt; espO; i++ )
				printf( &quot; &quot; );
			// Imprime los comodines
			for( i=0; i &lt; discoO; i++ )
				printf( &quot;*&quot; );
			// Espacios a la derecha
			for( i=0; i &lt; espO; i++ )
				printf( &quot; &quot; );

			// Se recoge el siguiente disco:
			discoO = extraeDatoDeLaPila(&amp;pilaOc, &amp;nivelO);
		}
		else
		{
			// Se rellena todo de espacios ya que no hay disco en ese altura:
			for( i=0; i &lt; tamDiscGrande; i++ )
				printf( &quot; &quot; );
		};

		printf( &quot;  &quot; );

		// Torre 1 o Auxiliar:
		if( nivelA == numNivel )
		{
			// Espacios a la izquierda
			for( i=0; i &lt; espA; i++ )
				printf( &quot; &quot; );
			// Imprime los comodines
			for( i=0; i &lt; discoA; i++ )
				printf( &quot;*&quot; );
			// Espacios a la derecha
			for( i=0; i &lt; espA; i++ )
				printf( &quot; &quot; );

			discoA = extraeDatoDeLaPila(&amp;pilaAc, &amp;nivelA);
		}
		else
		{
			// Se rellena todo de espacios ya que no hay disco en ese altura:
			for( i=0; i &lt; tamDiscGrande; i++ )
				printf( &quot; &quot; );
		};

		printf( &quot;  &quot; );

		// Torre 1 o Destino:
		if( nivelD == numNivel )
		{
			// Espacios a la izquierda
			for( i=0; i &lt; espD; i++ )
				printf( &quot; &quot; );
			// Imprime los comodines
			for( i=0; i &lt; discoD; i++ )
				printf( &quot;*&quot; );
			// Espacios a la derecha
			for( i=0; i &lt; espD; i++ )
				printf( &quot; &quot; );

			discoD = extraeDatoDeLaPila(&amp;pilaDc, &amp;nivelD);
		}
		else
		{
			// Se rellena todo de espacios ya que no hay disco en ese altura:
			for( i=0; i &lt; tamDiscGrande; i++ )
				printf( &quot; &quot; );
		};

		// Se hace un salto de linea para representar la próxima altura:
		printf( &quot;\n&quot; );

	};

};

// FUNCIÓN QUE MUEVE UN DISCO DE UNA PILA A OTRA:
void mueveDisco( struct NODO **pilaO, struct NODO **pilaA, struct NODO **pilaD, int totDiscos, int tamDiscGrande, char listOrigen, char listDestino )
{
	/*
	Precondición:
					pilaO, pilaA, pilaD			Se reciben tres dobles punteros a tres pilas de tipo struct NODO.
					totDiscos					Parámetro de tipo entero que indica el numero de discos totales para calcular el tiempo de pausa por cada impresión.
					tamDiscGrande				Parámetro de tipo entero que indica el tamaño del disco mas grande, se emplea para calcular los espacios a imprimir a ambos lados del disco.
					listOrigen, listDestino		Dos enteros que indican el origen del disco y su destino.
	Poscondición:
					Se mueve el disco de Origen a Destino y se llama a la función que imprime el tablero.
	*/

	int paraNada=0;

	if( listOrigen == 'O' )
	{
		if( listDestino == 'A' )
			insertaDatoEnLaPila( pilaA, extraeDatoDeLaPila(pilaO, &amp;paraNada) );

		else if( listDestino == 'D' )
			insertaDatoEnLaPila( pilaD, extraeDatoDeLaPila(pilaO, &amp;paraNada) );
	}
	else if( listOrigen == 'A' )
	{
		if( listDestino == 'O' )
			insertaDatoEnLaPila( pilaO, extraeDatoDeLaPila(pilaA, &amp;paraNada) );

		else if( listDestino == 'D' )
			insertaDatoEnLaPila( pilaD, extraeDatoDeLaPila(pilaA, &amp;paraNada) );
	}
	else if( listOrigen == 'D' )
	{
		if( listDestino == 'O' )
			insertaDatoEnLaPila( pilaO, extraeDatoDeLaPila(pilaD, &amp;paraNada) );

		else if( listDestino == 'A' )
			insertaDatoEnLaPila( pilaA, extraeDatoDeLaPila(pilaD, &amp;paraNada) );
	};

	// Se imprime el tablero:
	imprimeTablero( pilaO, pilaA, pilaD, totDiscos, tamDiscGrande );
};

// FUNCIÓN DE HANOI MEDIANTE RECURSIVIDAD:
void hanoi( struct NODO **pilaO, struct NODO **pilaA, struct NODO **pilaD, int nDiscos, int totDiscos, int tamDiscGrande, char O, char A, char D )
{
/*
Precondición:
				pilaO, pilaA, pilaD		Se reciben tres dobles punteros a tres pilas de tipo struct NODO.
				nDiscos					Parámetro de tipo entero que indica el numero de discos usados en cada recursividad.
				totDiscos				Parámetro de tipo entero que indica el numero de discos totales para calcular el tiempo de pausa por cada impresión.
				tamDiscGrande			Parámetro de tipo entero que indica el tamaño del disco mas grande, se emplea para calcular los espacios a imprimir a ambos lados del disco.
				O, A, D					Tres enteros que indican la fila desde donde se ha de coger el disco y a donde se ha de traspasar. La primera vez que se llama a hanoi tienen los valores de: 0 ,1 y 2 respectivamente.
Poscondición:
				Se llama recursivamente a hanoi hasta resolver el tablero.
*/

	if( nDiscos == 1 )
	{
		// Se borra la pantalla, se mueve el disco/imprime y se hace una pausa que varia dependiendo del numero de discos:
		system(&quot;clear&quot;);
		mueveDisco( pilaO, pilaA, pilaD, totDiscos, tamDiscGrande, O, D );
		if(totDiscos15) system(&quot;sleep 0.02&quot;);
	}
	else
	{
		hanoi( pilaO, pilaA, pilaD, nDiscos-1, totDiscos, tamDiscGrande, O, D, A );

		system(&quot;clear&quot;);
		mueveDisco( pilaO, pilaA, pilaD, totDiscos, tamDiscGrande, O, D );
		if(totDiscos15) system(&quot;sleep 0.02&quot;);

		hanoi( pilaO, pilaA, pilaD, nDiscos-1, totDiscos, tamDiscGrande, A, O, D );
	};

};

main()
{

	struct NODO *pilaO=NULL, *pilaA=NULL, *pilaD=NULL;
	int nDiscos, disco, tamDiscGrande, i;

	printf( &quot;Indique el número de discos: &quot; );
	scanf( &quot;%i&quot;, &amp;nDiscos );

	// Se halla el disco más grande (de tamaño impar) que se usara:
	disco = 1 + 2*(nDiscos - 1);
	tamDiscGrande = disco; // Se hace una copia para poder conservar el numero.

	for( i=0; i &lt; nDiscos; i++ )
	{
		// Se introduce el disco que corresponda y se resta 2 para la siguiente iteración:
		insertaDatoEnLaPila( &amp;pilaO, disco );
		disco -= 2;
	};

	// Se imprime el tablero:
	system(&quot;clear&quot;);
	imprimeTablero( &amp;pilaO, &amp;pilaA, &amp;pilaD, nDiscos, tamDiscGrande );
	system(&quot;sleep 1&quot;);

	// Se llama a hanoi para comenzar &quot;la partida&quot;:
	hanoi( &amp;pilaO, &amp;pilaA, &amp;pilaD, nDiscos, nDiscos, tamDiscGrande, 'O', 'A', 'D' );

	// Se borran la pila de destino que es la única que tiene nodos:
	borrarLista( &amp;pilaD );

};
</pre>
]]></content:encoded>
			<wfw:commentRss>http://giltesa.com/2012/02/09/6%c3%9705-torres-de-hanoi-con-pilas/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>6&#215;04: Notación polaca inversa con pilas</title>
		<link>http://giltesa.com/2012/02/07/6x04-notacion-polaca-inversa-con-pilas/</link>
		<comments>http://giltesa.com/2012/02/07/6x04-notacion-polaca-inversa-con-pilas/#comments</comments>
		<pubDate>Tue, 07 Feb 2012 22:13:40 +0000</pubDate>
		<dc:creator>giltesa</dc:creator>
				<category><![CDATA[C]]></category>
		<category><![CDATA[Programación]]></category>

		<guid isPermaLink="false">http://giltesa.com/?p=8911</guid>
		<description><![CDATA[]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><a href="http://giltesa.com/wp-content/uploads/2012/02/Notacion-polaca-inversa.png"><img class="alignnone size-medium wp-image-8912" title="Notacion polaca inversa" src="http://giltesa.com/wp-content/uploads/2012/02/Notacion-polaca-inversa-470x251.png" alt="Notación polaca inversa en C con Pilas" width="470" height="251" /></a></p>
<p><span id="more-8911"></span></p>
<pre class="brush: cpp; title: ; notranslate">
/*
6x04-Notacion_postfija_con_pilas
07/02/2012

Escribe un programa que lea de teclado una expresión en notación postfija y la evalúe, mostrando su resultado por pantalla. Para ello implementa y utiliza una pila.
*/
/*
NOTAS:

Infija		a+b		(((5+9)*2)+(6*5))	= 58
Prefija 	+ab
Postfija	ab+		5 9+2*6 5*+			= 58

Si el termino es un valor, introducirlo en una pila
Sí el término es un operador:

Sacar dos operandos de la pila
Aplicar el operador
Meter el resultado en la pila

	Paso a paso:
	5
	9 5
	14
	2 14
	28
	6 28
	5 6 28
	30 28
	58
*/

#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include &lt;stdlib.h&gt;

struct NODO
{
	int valor;
	struct NODO *puntero;
};

// FUNCIÓN QUE PASA UNA CADENA CON NUMEROS A ENTERO:
int pasaCadenaAEntero( char cadena[20] )
{
	/*
	Precondición:
					Se ha de recibir una cadena de caracteres terminada en fin de linea que contenga solo un numero entero de máximo 20 dígitos.
	Poscondición:
					Se pasa esa cadena al tipo entero y se devuelve el valor.
	*/

	int longCadena=strlen(cadena), numero=0, i;

	for( i=0; i&lt;longCadena; i++ )
	{
		numero *= 10;
		numero += cadena[i]-48;
	};

	return numero;
};

// FUNCIÓN QUE INTRODUCE UN NUMERO EN UNA PILA:
void insertaDatoEnLaPila( struct NODO **pila, int num )
{
	/*
	Precondición:
					Se ha de recibir un doble puntero de tipo struct NODO para una pila, y un parámetro de tipo entero.
	Poscondición:
					Se introduce el numero recibido en la pila.
	*/

	struct NODO *temp = (struct NODO *) malloc(sizeof(struct NODO));

	temp-&gt;valor		= num;
	temp-&gt;puntero	= *pila;
	*pila			= temp;

};

// FUNCIÓN QUE EXTRAE EL PRIMER ELEMENTO DE LA PILA Y BORRA EL NODO VACIO:
int extraeDatoDeLaPila( struct NODO **pila )
{
	/*
	Precondición:
					Se ha de recibir un doble puntero de tipo struct NODO para una pila.
	Poscondición:
					Se devuelve el primer parámetro de tipo entero almacenado en la pila.
	*/

	struct NODO *siguiente;
	int resp;

	// Se copia el valor a la variable que va a ser retornada por la función:
	resp = (*pila)-&gt;valor;

	// Se elimina el primer Nodo (el vaciado):
	siguiente = (*pila)-&gt;puntero;
	free(*pila);
	*pila = siguiente;

	return resp;
};

// FUNCIÓN QUE LIBERA LA MEMORIA USADA POR UNA LISTA:
void listaLiberaRam( struct NODO **lista )
{
	/*
	Precondición:
					Se ha de recibir un puntero de tipo struct NODO al primer nodo de la lista.
	Poscondición:
					Se borran todos los nodos de esa lista hasta llegar a NULL.
	*/

	struct NODO *actual, *siguiente;
	actual = *lista;

	while(actual != NULL)
	{
		siguiente = actual-&gt;puntero;
		free(actual);
		actual = siguiente;
	};

	*lista = NULL;

};

main()
{

	struct NODO *pila;
	char cad[20];
	int val1, val2;

	printf( &quot;Introduce una expresión en notación postfija para hallar el resultado.\n&quot; );
	printf( &quot;Introduzca un valor o operador y pulse intro para introducir el siguiente, escriba = para calcular el resultado\n&quot; );
	printf( &quot;  Ejemplo:\n\n   5\n   9\n   +\n   2\n   *\n   6\n   5\n   *\n   +\n\n&quot; );
	printf( &quot;Indique la expresion:\n\n&quot; );

	do{

		// Se lee un valor o operador:
		scanf( &quot;%s&quot;, cad );

		// Dependiendo de lo leido se hace una operacion u otra:
		switch( cad[0] )
		{
			case '+':
				// En el caso de la: '+', '-', '*' y '/', se sacan dos valores de la pila, se opera con ellos según el operador elegido y se guarda el resultado en la pila.

				val1 = extraeDatoDeLaPila( &amp;pila );
				val2 = extraeDatoDeLaPila( &amp;pila );
				insertaDatoEnLaPila( &amp;pila, val1 + val2 );
			break;

			case '-':
				val1 = extraeDatoDeLaPila( &amp;pila );
				val2 = extraeDatoDeLaPila( &amp;pila );
				insertaDatoEnLaPila( &amp;pila, val1 - val2 );
			break;

			case '*':
				val1 = extraeDatoDeLaPila( &amp;pila );
				val2 = extraeDatoDeLaPila( &amp;pila );
				insertaDatoEnLaPila( &amp;pila, val1 * val2 );
			break;

			case '/':
				val1 = extraeDatoDeLaPila( &amp;pila );
				val2 = extraeDatoDeLaPila( &amp;pila );
				insertaDatoEnLaPila( &amp;pila, val1 / val2 );
			break;

			case '=':
				// Se imprime por pantalla el ultimo y único elemento de la pila.
				printf( &quot;\nEl resultado es: %i\n\n&quot;, extraeDatoDeLaPila( &amp;pila ) /*pila-&gt;valor*/ );
			break;

			default:
				// Se introduce un nuevo dato en la pila:
				insertaDatoEnLaPila( &amp;pila, pasaCadenaAEntero(cad) );
			break;
		};

	} while( cad[0] != '=' );

};
</pre>
]]></content:encoded>
			<wfw:commentRss>http://giltesa.com/2012/02/07/6x04-notacion-polaca-inversa-con-pilas/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>6&#215;02: Lista desordenada</title>
		<link>http://giltesa.com/2012/02/05/6x02-lista-desordenadas/</link>
		<comments>http://giltesa.com/2012/02/05/6x02-lista-desordenadas/#comments</comments>
		<pubDate>Sun, 05 Feb 2012 17:14:44 +0000</pubDate>
		<dc:creator>giltesa</dc:creator>
				<category><![CDATA[C]]></category>
		<category><![CDATA[Programación]]></category>

		<guid isPermaLink="false">http://giltesa.com/?p=8893</guid>
		<description><![CDATA[]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><a href="http://giltesa.com/wp-content/uploads/2012/02/6x02-Lista_enlazadas_desordenadass.jpg"><img class="alignnone size-medium wp-image-8894" title="6x02-Lista_enlazadas_desordenadass" src="http://giltesa.com/wp-content/uploads/2012/02/6x02-Lista_enlazadas_desordenadass-223x270.jpg" alt="" width="223" height="270" /></a></p>
<p><span id="more-8893"></span></p>
<pre class="brush: cpp; title: ; notranslate">
/*
6x02-Lista_enlazadas_desordenadas
01/02/2012

Repite el ejercicio anterior usando una lista (no ordenada), que implemente una operación de ordenarLista.
Se almacenarán los números desordenados en la lista y luego se aplicará la operación implementada.
*/

// Estructuras de datos:
struct SORTEO
{
	int numero;		// Numero de boleto
	int cuantia;	// Importe del premio
};
struct NODO
{
	struct SORTEO elemento;	// Información contenida en cada nodo de la lista.
	struct NODO *puntero;	// Puntero al siguiente nodo de la lista.
};

// Constantes:
#define NUMEROS 10

// Librerias:
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;time.h&gt;
//#include &quot;listas.h&quot;

// FUNCION QUE INSERTA NODOS AL FINAL DE LA LISTA:
void listaInsertAlFinal( struct NODO **lista, struct SORTEO *cupon )
{
	/*
	Precondición:
					Se ha de recibir un puntero de tipo struct NODO al primer nodo de la lista. Este podrá valer NULL la primera vez o la dirección de memoria que corresponda.
					  El puntero además es un &quot;doble puntero&quot; ya que es necesario poder modificarlo.
					También se ha de recibir un puntero a una estructura de tipo SORTEO con la información a insertar en la lista.
	Poscondición:
					Se inserta la información contenida en &quot;cupon&quot; en un Nodo nuevo perteneciente a &quot;lista&quot;, la inserción se realiza siempre al final de la lista.
	*/

	struct NODO *temp 		= (struct NODO *)malloc(sizeof(struct NODO));	// Se define un puntero temporal de tipo NODO que apunta a la memoria solicitada al sistema.
	struct NODO *anterior 	= NULL;											// Se crea otro puntero de tipo NODO, este apuntando a NULL
	struct NODO *siguiente 	= *lista;										// Y un tercer puntero de tipo NODO que apunta al primer nodo de la lista.

	// En la primera inserción &quot;lista&quot; no apuntara a nada, por lo que se inserta el primer nodo y se hace que &quot;lista&quot; apunte a él.
	if( *lista == NULL )
	{
		temp-&gt;elemento	= *cupon;
		temp-&gt;puntero	= NULL;

		*lista = temp;
	}
	  // Cuando la lista ya tenga un elemento...
	else
	{

		// Se recorren todos los Nodos de la lista hasta llegar al final.
		while( siguiente != NULL )
		{
			anterior = siguiente;
			siguiente = siguiente-&gt;puntero;
		};

		// Se agrega el nuevo Nodo al final de la lista.
		if( siguiente == NULL )
		{
			temp-&gt;elemento	= *cupon;	// Se guarda la estructura de datos (cupon) en la estructura del nuevo Nodo.
			temp-&gt;puntero	= NULL;		// Como la inserción es al final de la lista el puntero del Nodo no a puntara a ningún otro Nodo.

			anterior-&gt;puntero = temp;	// Se modifica el puntero del Nodo anterior para que apunte al nuevo Nodo.
		};

	};

};

// FUNCION QUE ORDENA LOS NODOS DE UNA LISTA DE FORMA ASCENDENTE:
void listaOrdenarAscendente( struct NODO **lista )
{
	/*
	Precondición:
					Se ha de recibir un puntero de tipo struct NODO al primer nodo de la lista. Este podrá valer NULL la primera vez o la dirección de memoria que corresponda.
	Poscondición:
					La función se encarga de ordenar de forma ascendente cada Nodo de la lista según el numero de cupón que contengan dichos nodos.
					El método usado para ordenar los nodos es mediante el método de la burbuja, de modo que se necesitan dos bucles,
					  el segundo se encarga de ordenar el nodoA y el nodoB en la primera iteración, después el nodoB y el nodoC en la segunda iteración, luego el nodoC y el nodoD, etc.
					  de modo que se van arrastrando los números pequeños hacia el principio de la lista, una vez recorrida entera el segundo bucle se encarga de recorrerla de nuevo, así tantas veces como nodos tiene la lista.
					Finalmente la lista queda ordenada completamente.
					Esquema gráfico: http://goo.gl/I54uV
	*/

	struct NODO *p_nodoAnt2_nodoAnt1	= NULL;							// Es(sera) el puntero del puntero que apunta al nodoA (es necesario para modificar el puntero que apunta a A)
	struct NODO *p_nodoAnt1_nodoA		= *lista;						// Es el puntero que apunta al nodoA
	struct NODO *p_nodoA_nodoB			= p_nodoAnt1_nodoA-&gt;puntero;	// Es el puntero del nodoA y apunta al nodoB
	struct NODO *p_nodoB_sig			= p_nodoA_nodoB-&gt;puntero;		// Es el puntero del nodoB que apunta al siguiente nodo.

	struct NODO *temporal				= NULL;							// Puntero temporal de intercambio.
	struct NODO *iteracion				= *lista;						// Es el puntero que va avanzando en la lista en cada iteración del primer bucle, es necesario para saber cuando detener el bucle.

	int salirBucle1; // Variables &quot;booleanas&quot; para indicar cuando se ha de salir de los bucles.
	int salirBucle2;

	// Si la lista contiene Nodos se ordenan:
	if( *lista != NULL )
	{

		salirBucle1 = 0;

		// La lista se ha de recorrer tantas veces como Nodos tenga:
		while( !salirBucle1 )
		{

			// Si &quot;iteracion&quot; es NULL se cambia el estado de &quot;salirBucle1&quot; para salir del primer bucle una vez se haya hecho una ultima vez el bucle 2.
			// En caso contrario iteración avanza un nodo de la lista.
			if( iteracion == NULL )
				salirBucle1 = 1;
			else
				iteracion = iteracion-&gt;puntero;

			salirBucle2 = 0;

			// Cada vez que se recorre la lista se ordenan dos Nodos:
			while( !salirBucle2 )
			{

				// Si se va a ordenar el primer Nodo con el segundo...
				if( p_nodoAnt1_nodoA == *lista )
				{
					// Si el NodoA es mayor que el nodoB, se cambian de orden:
					if( p_nodoAnt1_nodoA-&gt;elemento.numero   &gt;   p_nodoA_nodoB-&gt;elemento.numero )
					{
						// Se intercambia el NodoA con el NodoB:
						*lista						= p_nodoA_nodoB;
						temporal					= p_nodoB_sig;
						p_nodoA_nodoB-&gt;puntero		= p_nodoAnt1_nodoA;
						p_nodoAnt1_nodoA-&gt;puntero	= temporal;

						// Se actualizan los punteros para que cada uno apunte segun su nombre correspondiente:
						p_nodoAnt1_nodoA			= *lista;
						p_nodoA_nodoB				= p_nodoAnt1_nodoA-&gt;puntero;
						p_nodoB_sig					= p_nodoA_nodoB-&gt;puntero;
					};

				}
				  // Si se van a ordenar nodos intermedios de la lista...
				else if( p_nodoB_sig != NULL )
				{

					if( p_nodoAnt1_nodoA-&gt;elemento.numero   &gt;   p_nodoA_nodoB-&gt;elemento.numero )
					{
						// Se intercambian los punteros:
						p_nodoAnt2_nodoAnt1-&gt;puntero	= p_nodoA_nodoB;
						temporal						= p_nodoB_sig;
						p_nodoA_nodoB-&gt;puntero			= p_nodoAnt1_nodoA;
						p_nodoAnt1_nodoA-&gt;puntero		= temporal;

						// Se actualizan los punteros para que cada uno apunte segun su nombre correspondiente:
						p_nodoAnt1_nodoA				= p_nodoAnt2_nodoAnt1-&gt;puntero;
						p_nodoA_nodoB					= p_nodoAnt1_nodoA-&gt;puntero;
						p_nodoB_sig						= p_nodoA_nodoB-&gt;puntero;
					};

				}
				  // Si se va a ordenar el penultimo y ultimo nodo...
				else if( p_nodoB_sig == NULL )
				{

					if( p_nodoAnt1_nodoA-&gt;elemento.numero   &gt;   p_nodoA_nodoB-&gt;elemento.numero )
					{
						// Se intercambian los punteros:
						p_nodoAnt2_nodoAnt1-&gt;puntero	= p_nodoA_nodoB;
						p_nodoA_nodoB-&gt;puntero			= p_nodoAnt1_nodoA;
						p_nodoAnt1_nodoA-&gt;puntero		= NULL;

						// Se actualizan los punteros para que cada uno apunte segun su nombre correspondiente:
						p_nodoAnt1_nodoA				= p_nodoAnt2_nodoAnt1-&gt;puntero;
						p_nodoA_nodoB					= p_nodoAnt1_nodoA-&gt;puntero;
						p_nodoB_sig						= NULL;
					}

					// Ya se han ordenado los dos últimos Nodos y ahora se para el bucle2:
					salirBucle2 = 1;

				};

				// Mientras el nodoB siga apuntando a otro nodo, se modifican todos los punteros para que apunten al siguiente nodo:
				if( p_nodoB_sig != NULL )
				{
					p_nodoAnt2_nodoAnt1	= p_nodoAnt1_nodoA;
					p_nodoAnt1_nodoA	= p_nodoAnt1_nodoA-&gt;puntero;
					p_nodoA_nodoB		= p_nodoA_nodoB-&gt;puntero;
					p_nodoB_sig			= p_nodoB_sig-&gt;puntero;
				};

			}; // Fin primer bucle

			// Al parar el segundo bucle hay que resetear los punteros al valor original.
			p_nodoAnt2_nodoAnt1		= NULL;
			p_nodoAnt1_nodoA		= *lista;
			p_nodoA_nodoB			= p_nodoAnt1_nodoA-&gt;puntero;
			p_nodoB_sig				= p_nodoA_nodoB-&gt;puntero;

		}; // Fin segundo bucle

	};// Fin del if

}; // fin de la funcion

// FUNCION QUE LIBERA LA MEMORIA USADA POR UNA LISTA:
void listaLiberaRam( struct NODO **lista )
{
	/*
	Precondición:
					Se ha de recibir un puntero de tipo struct NODO al primer nodo de la lista.
	Poscondición:
					Se borran todos los nodos de esa lista hasta llegar a NULL.
	*/

	struct NODO *actual, *siguiente;
	actual = *lista;

	while(actual != NULL)
	{
		siguiente = actual-&gt;puntero;
		free(actual);
		actual = siguiente;
	};

	*lista = NULL;

};

// Función que genera números aleatorios con sus premios aleatorios respectivos y los guarda en &quot;fichero.dat&quot;:
void generaDat()
{
	/*
	Poscondición:
					La función se encarga de generar estructuras con números aleatorios que son guardados en un fichero secuencial.
					  El numero de estructuras a guardar viene dado por la constante NUMEROS.
	*/

	FILE *ficheroBin = fopen( &quot;sorteo.dat&quot;, &quot;w&quot; );
	struct SORTEO cupon;
	int i;

	srand((unsigned int)time(NULL));

	for( i=0; i &lt; NUMEROS; i++ )
	{
		cupon.numero  = rand()%100000;
		cupon.cuantia = rand()%1000;

		fwrite( &amp;cupon, sizeof(struct SORTEO), 1, ficheroBin );
	};

	fclose( ficheroBin );
};

// Funciona que pasa el contenido de &quot;fichero.dat&quot; a &quot;fichero.txt&quot;:
void mostrarDat()
{
	/*
	Poscondición:
					Se pasa todo el contenido del fichero secuencial a un fichero de texto.
	*/

	FILE *ficheroBin = fopen( &quot;sorteo.dat&quot;, &quot;r&quot; );
	FILE *ficheroText;
	struct SORTEO cupon;

	if( ficheroBin == NULL )
		printf( &quot;Genere rimero el fichero \&quot;sorteo.dat\&quot;\n&quot; );
	else
	{
		ficheroText = fopen( &quot;sorteo.txt&quot;, &quot;w&quot; );

		fread( &amp;cupon, sizeof(struct SORTEO), 1, ficheroBin );

		while( !feof(ficheroBin) )
		{
			fprintf( ficheroText, &quot;%i\t%i\n&quot;, cupon.numero, cupon.cuantia );
			fread( &amp;cupon, sizeof(struct SORTEO), 1, ficheroBin );
		};

		fclose( ficheroBin );
		fclose( ficheroText );

	};

};

main()
{
	struct NODO *lista = NULL;
	struct NODO *temp;
	struct SORTEO cupon;
	FILE *fichOriginal, *fichOrdenDat, *fichOrdenTxt;
	char opcion;

	printf( &quot;Eliga una opcion:\n&quot; );
	printf( &quot;1. Ordenar el fichero \&quot;sorteo.dat\&quot; mediante listas\n&quot; );
	printf( &quot;2. Generar \&quot;sorteo.dat\&quot;\n&quot; );
	printf( &quot;3. Pasar fichero \&quot;sorteo.dat\&quot; a \&quot;sorteo.txt\&quot;\n&quot; );
	do{
		scanf( &quot;%c&quot;, &amp;opcion );
	} while( opcion &lt; '1'  ||  opcion &gt; '3' );

	if( opcion == '2' )
		generaDat();
	else if( opcion == '3' )
		mostrarDat();
	else if( opcion == '1' )
	{

		fichOriginal = fopen(&quot;sorteo.dat&quot;, &quot;r&quot;);

		// Se comprueba que el fichero secuencial con el que se ha de trabajar exista:
		if( fichOriginal == NULL )
			printf( &quot;Necesita el fichero \&quot;sorteo.dat\&quot;, generelo primero\n&quot; );
		else
		{

			// Se recorre cada estructura del fichero secuencial y se inserta en una estructura de datos dinamica de tipo lista:
			fread( &amp;cupon, sizeof(struct SORTEO), 1, fichOriginal );

			while( !feof(fichOriginal) )
			{
				listaInsertAlFinal( &amp;lista, &amp;cupon );						// Se crea un nuevo nodo para el estruct leido y se inserta en la lista.
				fread( &amp;cupon, sizeof(struct SORTEO), 1, fichOriginal );	// Se lee la siguiente estructura de datos a guardar en la lista.
			};
			fclose(fichOriginal);

			// Se ordena la lista:
			listaOrdenarAscendente( &amp;lista );

			// Se imprime el contenido de la lista en unos ficheros:
			fichOrdenDat = fopen(&quot;sorteoOrdenado.dat&quot;, &quot;w&quot;);
			fichOrdenTxt = fopen(&quot;sorteoOrdenado.txt&quot;, &quot;w&quot;);
			temp = lista;

			while( temp != NULL )
			{
				fwrite( &amp;temp, sizeof(struct SORTEO), 1, fichOrdenDat );
				fprintf( fichOrdenTxt, &quot;%i\t%i\n&quot;, temp-&gt;elemento.numero, temp-&gt;elemento.cuantia );
				temp = temp-&gt;puntero;
			};
			fclose(fichOrdenDat);
			fclose(fichOrdenTxt);

			// Ya se ha finalizado el programa, pero antes de terminar del todo hay que liberar toda la memoria RAM usada:
			listaLiberaRam( &amp;lista );

		};

	};

	printf( &quot;  Operación finalizada.\n&quot; );

};
</pre>
]]></content:encoded>
			<wfw:commentRss>http://giltesa.com/2012/02/05/6x02-lista-desordenadas/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>6&#215;01: Lista ordenada</title>
		<link>http://giltesa.com/2012/02/01/6x01-lista-ordenada/</link>
		<comments>http://giltesa.com/2012/02/01/6x01-lista-ordenada/#comments</comments>
		<pubDate>Wed, 01 Feb 2012 14:44:12 +0000</pubDate>
		<dc:creator>giltesa</dc:creator>
				<category><![CDATA[C]]></category>
		<category><![CDATA[Programación]]></category>

		<guid isPermaLink="false">http://giltesa.com/?p=8835</guid>
		<description><![CDATA[]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><a href="http://giltesa.com/wp-content/uploads/2012/01/listas-1.jpg"><img class="alignnone size-medium wp-image-8839" title="listas-1" src="http://giltesa.com/wp-content/uploads/2012/01/listas-1-247x270.jpg" alt="" width="247" height="270" /></a></p>
<p><span id="more-8835"></span></p>
<pre class="brush: cpp; title: ; notranslate">
/*
6x01-Listas_ordenadas_al_instante
25/01/2012

Implementa una lista ordenada con las operaciones vistas en clase. Utilízala para almacenar en ella todos los datos que hay en un fichero (por ejemplo, uno de resultados de un sorteo de lotería de Navidad, que tenga números premiados y premio que corresponde, que esté desordenado, y usando como criterio de orden los números), y posteriormente guarda la lista ordenada
en otro fichero.
*/

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;time.h&gt;

#define NUMEROS 10

struct SORTEO
{
	int numero;		// Numero de boleto
	int cuantia;	// Importe del premio
};

struct NODO
{
	struct SORTEO elemento;	// Información contenida en cada nodo de la lista.
	struct NODO *puntero;	// Puntero al siguiente nodo de la lista.
};

void insertarEnListaOrdenada( struct NODO **lista, struct SORTEO *cupon )
{
	/*
	Precondición:
					Se ha de recibir un puntero de tipo struct NODO al primer nodo de la lista. Este podrá valer NULL la primera vez o la dirección de memoria que corresponda.
					  El puntero además es un &quot;doble puntero&quot; ya que es necesario poder modificarlo.
					También se ha de recibir un puntero a una estructura de tipo SORTEO con la información a insertar en la lista.
	Poscondición:
					Se inserta la información contenida en &quot;cupon&quot; en un Nodo nuevo perteneciente a &quot;lista&quot;, la inserción se realiza con orden ascendente según el &quot;numero&quot; de la estructura &quot;cupon&quot;
	*/

	struct NODO *temp 		= (struct NODO *)malloc(sizeof(struct NODO));	// Se define un puntero temporal de tipo NODO que apunta a la memoria solicitada al sistema.
	struct NODO *anterior 	= NULL;											// Se crea otro puntero de tipo NODO, este apuntando a NULL
	struct NODO *siguiente 	= *lista;										// Y un tercer puntero de tipo NODO que apunta al primer nodo de la lista.

	// En la primera inserción &quot;lista&quot; no apuntara a nada, por lo que se inserta el primer nodo y se hace que &quot;lista&quot; apunte a él.
	if( *lista == NULL )
	{
		temp-&gt;elemento	= *cupon;
		temp-&gt;puntero	= NULL;

		*lista = temp;
	}
	  // Cuando la lista ya tenga al un elemento...
	else
	{

		// Se han de recorrer todos los nodos para comprobar que el orden es correcto, es decir, con orden ascendente:
		//  De modo que se compara el numero del nodo al cual apunta &quot;siguiente&quot; con el numero del cupón que se quiere insertar.
		//  Si se cumple la condición, se guarda en &quot;anterior&quot; el puntero actual, y en &quot;siguiente&quot; se guarda el puntero del nodo siguiente de la lista
		//  En caso de que termine la lista &quot;siguiente&quot; valdrá NULL y &quot;anterior&quot; valdrá N-1 (el ultimo puntero valido)
		while(  siguiente != NULL   &amp;&amp;   siguiente-&gt;elemento.numero &lt; cupon-&gt;numero )
		{
			anterior = siguiente;
			siguiente = siguiente-&gt;puntero;
		};

		// Si durante la lectura de la lista se llega al final sin encontrar un numero mayor, entonces se inserta el nuevo nodo al final de la lista.
		if( siguiente == NULL )
		{
			temp-&gt;elemento	= *cupon;	// Se guarda la estructura de datos (cupón) en la estructura del nuevo Nodo.
			temp-&gt;puntero	= NULL;		// Como la inserción es al final de la lista el puntero del Nodo no a puntara a ningún otro Nodo.

			anterior-&gt;puntero = temp;	// Se modifica el puntero del Nodo anterior para que apunte al nuevo Nodo.
		}
		  // En cambio, si recorriendo la lista se encuentra un numero mayor, se deberá insertar el nuevo nodo antes.
		else
		{
			// Ahora pueden darse dos casos:

			// Que el nodo a insertar sea el primero de todos, por lo tanto hay que modificar el puntero de &quot;lista&quot; para que apunte al nuevo Nodo:
			if( *lista == siguiente )
			{
				temp-&gt;elemento	= *cupon;
				temp-&gt;puntero	= siguiente;

				*lista = temp;
			}
			  // O que este entre dos nodos, por lo que se modificara el puntero del anterior Nodo para que apunte al nuevo Nodo:
			else
			{
				temp-&gt;elemento = *cupon;
				temp-&gt;puntero = siguiente;

				anterior-&gt;puntero = temp;
			};

		};

	};

};

void borrarLista( struct NODO **lista )
{
	/*
	Precondición:
					Se ha de recibir un puntero de tipo struct NODO al primer nodo de la lista.
	Poscondición:
					Se borran todos los nodos de esa lista hasta llegar a NULL.
	*/

	struct NODO *actual, *siguiente;
	actual = *lista;

	while(actual != NULL)
	{
		siguiente = actual-&gt;puntero;
		free(actual);
		actual = siguiente;
	};

	*lista = NULL;

};

// Función que genera números aleatorios con sus premios aleatorios respectivos y los guarda en &quot;fichero.dat&quot;:
void generaDat()
{
	/*
	Poscondición:
					La función se encarga de generar estructuras con números aleatorios que son guardados en un fichero secuencial.
					  El número de estructuras a guardar viene dado por la constante NUMEROS.
	*/

	FILE *ficheroBin = fopen( &quot;sorteo.dat&quot;, &quot;w&quot; );
	struct SORTEO cupon;
	int i;

	srand((unsigned int)time(NULL));

	for( i=0; i &lt; NUMEROS; i++ )
	{
		cupon.numero  = rand()%100000;
		cupon.cuantia = rand()%1000;

		fwrite( &amp;cupon, sizeof(struct SORTEO), 1, ficheroBin );
	};

	fclose( ficheroBin );
};

// Funcion que pasa el contenido de &quot;fichero.dat&quot; a &quot;fichero.txt&quot;:
void mostrarDat()
{
	/*
	Poscondición:
					Se pasa todo el contenido del fichero secuencial a un fichero de texto.
	*/

	FILE *ficheroBin = fopen( &quot;sorteo.dat&quot;, &quot;r&quot; );
	FILE *ficheroText;
	struct SORTEO cupon;

	if( ficheroBin == NULL )
		printf( &quot;Genere rimero el fichero \&quot;sorteo.dat\&quot;\n&quot; );
	else
	{
		ficheroText = fopen( &quot;sorteo.txt&quot;, &quot;w&quot; );

		fread( &amp;cupon, sizeof(struct SORTEO), 1, ficheroBin );

		while( !feof(ficheroBin) )
		{
			fprintf( ficheroText, &quot;%i\t%i\n&quot;, cupon.numero, cupon.cuantia );
			fread( &amp;cupon, sizeof(struct SORTEO), 1, ficheroBin );
		};

		fclose( ficheroBin );
		fclose( ficheroText );

	};

};

main()
{
	struct NODO *lista = NULL;
	struct NODO *temp;
	struct SORTEO cupon;
	FILE *fichOriginal, *fichOrdenDat, *fichOrdenTxt;
	char opcion;

	printf( &quot;Elija una opción:\n&quot; );
	printf( &quot;1. Ordenar el fichero \&quot;sorteo.dat\&quot; mediante listas\n&quot; );
	printf( &quot;2. Generar \&quot;sorteo.dat\&quot;\n&quot; );
	printf( &quot;3. Pasar fichero \&quot;sorteo.dat\&quot; a \&quot;sorteo.txt\&quot;\n&quot; );
	do{
		scanf( &quot;%c&quot;, &amp;opcion );
	} while( opcion &lt; '1'  ||  opcion &gt; '3' );

	if( opcion == '2' )
		generaDat();
	else if( opcion == '3' )
		mostrarDat();
	else if( opcion == '1' )
	{

		fichOriginal = fopen(&quot;sorteo.dat&quot;, &quot;r&quot;);

		// Se comprueba que el fichero secuencial con el que se ha de trabajar exista:
		if( fichOriginal == NULL )
			printf( &quot;Necesita el fichero \&quot;sorteo.dat\&quot;, genérelo primero\n&quot; );
		else
		{

			// Se recorre todo el fichero, en cada iteración se lee una estructura y se pasa a la función que la guarda en un nuevo Nodo de la lista.
			  // Se lee la primera estructura del fichero y se guarda en la estructura &quot;temporal&quot; de tipo &quot;SORTEO&quot;
			  fread( &amp;cupon, sizeof(struct SORTEO), 1, fichOriginal );

			while( !feof(fichOriginal) )
			{
				insertarEnListaOrdenada( &amp;lista, &amp;cupon );					// Se crea un nuevo nodo para el estruct leido y se inserta en la lista.
				fread( &amp;cupon, sizeof(struct SORTEO), 1, fichOriginal );	// Se lee la siguiente estructura de datos a guardar en la lista.
			};
			fclose(fichOriginal);

			// Hasta aquí ya se ha leído todo el fichero y se han introducido sus estructuras en cada Nodo de la lista de forma ordenada, ahora hay que pasarlos al fichero de destino.

			fichOrdenDat = fopen(&quot;sorteoOrdenado.dat&quot;, &quot;w&quot;);
			fichOrdenTxt = fopen(&quot;sorteoOrdenado.txt&quot;, &quot;w&quot;);
			temp = lista;

			while( temp != NULL )
			{
				fwrite( &amp;temp, sizeof(struct SORTEO), 1, fichOrdenDat );
				fprintf( fichOrdenTxt, &quot;%i\t%i\n&quot;, temp-&gt;elemento.numero, temp-&gt;elemento.cuantia );
				temp = temp-&gt;puntero;
			};
			fclose(fichOrdenDat);

			// Ya se ha finalizado el programa, pero antes de terminar del todo hay que liberar toda la memoria RAM usada:
			borrarLista( &amp;lista );

		};

	};

	printf( &quot;  Operación finalizada.\n&quot; );

};</pre>
]]></content:encoded>
			<wfw:commentRss>http://giltesa.com/2012/02/01/6x01-lista-ordenada/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>5&#215;07: Torres de Hanoi parte2</title>
		<link>http://giltesa.com/2012/01/25/5x07-torres-de-hanoi-parte2/</link>
		<comments>http://giltesa.com/2012/01/25/5x07-torres-de-hanoi-parte2/#comments</comments>
		<pubDate>Tue, 24 Jan 2012 23:02:57 +0000</pubDate>
		<dc:creator>giltesa</dc:creator>
				<category><![CDATA[C]]></category>
		<category><![CDATA[Programación]]></category>
		<category><![CDATA[Video]]></category>

		<guid isPermaLink="false">http://giltesa.com/?p=8807</guid>
		<description><![CDATA[]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><a href="http://giltesa.com/wp-content/uploads/2012/01/hanoi2.png"><img class="alignnone size-medium wp-image-8808" title="hanoi2" src="http://giltesa.com/wp-content/uploads/2012/01/hanoi2-470x89.png" alt="" width="470" height="89" /></a></p>
<p style="text-align: center;"><iframe width="560" height="315" src="http://www.youtube.com/embed/xXTle8JYhys" frameborder="0" allowfullscreen></iframe></p>
<p><span id="more-8807"></span></p>
<pre class="brush: cpp; title: ; notranslate">
/*
5x07-Torres_de_Hanoi_parte_2
24/01/2012

Escribe un programa (se recomienda que sea recursivo) que dé solución al problema de las torres de Hanoi.
El enunciado es el siguiente: Se dispone de una torre formada por varios discos de diferentes diámetros denominada torre O (origen), donde cada disco es de diámetro inferior a todos los que están por debajo. Se dispone de otras dos torres para dejar discos, una denominada torre A (auxiliar) y otra torre D (destino).
El problema consiste en pasar todos los discos de la torre O a la torre D respetando dos normas muy simples:

Los discos se pasan de una torre a otra de uno en uno.
Nunca un disco de mayor diámetro puede estar sobre otro de menor diámetro.
Se preguntará al inicio del programa por el tamaño de la torre O (entendiendo que tendrá el número de discos indicados, con algún límite preestablecido).
Las torres A y D estarán inicialmente vacías.
Se debe ofrecer la solución que da el programa a este problema paso a paso, mostrando el resultado de una forma gráfica. El inicio podría ser algo así:

			*
		   ***
		  *****
		 *******
		*********
	   ===========		==========		==========
			O				A				D
*/
/*
	Formula para calcular movimientos mínimos necesarios:
	m = 2^n -1

http://www.rodoval.com/heureka/hanoi/

*/

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

void imprime( int *tab, int fil, int col, int ultNum )
{
	/*
	Precondición:
					*tab	Puntero a una matriz de tipo entero.
					fil		Entero que indica el numero de filas de la matriz.
					col		Entero que indica el numero de columnas de la matriz.
					disc	Parámetro de tipo entero que indica el numero de discos usados.
					ultNum	Entero que indica el numero que esta usando el disco mas grande.
*/

	int f, c;
	int i, esp;

	for( c=col-1; c &gt;= 0; c-- )
	{
		for( f=0; f &lt; fil; f++ )
		{
			esp = ( ultNum - tab[col*f+c] )/2;

			// Espacios a la izquierda
			for( i=0; i &lt; esp; i++ )
				printf( &quot; &quot; );

			// Imprime los comodines
			for( i=0; i &lt; tab[col*f+c]; i++ )
				printf( &quot;*&quot; );

			// Espacios a la derecha
			for( i=0; i &lt; esp; i++ )
				printf( &quot; &quot; );

			printf( &quot;\t&quot; );
		};

		printf( &quot;\n&quot; );
	};

};

void mueveDisco( int *tab, int fil, int col, int ultNum, int filOrig, int filDest )
{
	/*
	Precondición:
					*tab	Puntero a una matriz de tipo entero.
					fil		Entero que indica el numero de filas de la matriz.
					col		Entero que indica el numero de columnas de la matriz.
					disc	Parámetro de tipo entero que indica el numero de discos usados.
					ultNum	Entero que indica el numero que esta usando el disco mas grande.
					filOrig	Entero que indica el numero de fila de la matriz en la cual hay que coger el numero/disco
					filDest	Entero que indica el numero de fila de la matriz en la cual hay que dejar el numero/disco.
	Poscondición:
					Se mueve el disco y se llama a la función que imprime el tablero.
	*/

	int cO=col-1, cD=col-1;

	// Se busca el disco que se encuentre mas arriba y por lo tanto el mas pequeño de la fila de origen.
	while( cO &gt;= 0  &amp;&amp;  tab[col*filOrig+cO] == 0 )
	{
		cO--;
	};
	if( cO &lt; 0 )
		cO = 0;

	// Ahora se calcula cual es la posición libre mas arriba de la fila de destino
	while( cD &gt;= 0  &amp;&amp;  tab[col*filDest+cD] == 0 )
	{
		cD--;
	};

	// Se mueve el disco de la fila de origen a la de destino:
	tab[col*filDest+cD+1] = tab[col*filOrig+cO];
	tab[col*filOrig+cO] = 0;

	// Se imprime el tablero:
	imprime( tab, fil, col, ultNum );
};

void hanoi( int *tab, int fil, int col, int disc, int ultNum, int O, int A, int D )
{
/*
Precondición:
				*tab	Puntero a una matriz de tipo entero.
				fil		Entero que indica el numero de filas de la matriz.
				col		Entero que indica el numero de columnas de la matriz.
				disc	Parámetro de tipo entero que indica el numero de discos usados.
				ultNum	Entero que indica el numero que esta usando el disco mas grande.
				O,A,D	Tres enteros que indican la fila desde donde se ha de coger el disco y a donde se ha de traspasar. La primera vez que se llama a hanoi tienen los valores de: 0 ,1 y 2 respectivamente.
Poscondición:
				Se llama recursivamente a hanoi hasta resolver el tablero.
*/

	if( disc==1 )
	{
		// Se borra la pantalla, se imprime la tabla y se hace una pausa que varia dependiendo del numero de discos:
		system(&quot;clear&quot;);
		mueveDisco( tab, fil, col, ultNum, O, D );
		if(col&lt;=5) system(&quot;sleep 0.8&quot;); else if(col&lt;=10) system(&quot;sleep 0.3&quot;); else if(col&lt;=15) system(&quot;sleep 0.06&quot;); else if(col&gt;15) system(&quot;sleep 0.02&quot;);
	}
	else
	{
		hanoi( tab, fil, col, disc-1, ultNum, O, D, A );

		system(&quot;clear&quot;);
		mueveDisco( tab, fil, col, ultNum, O, D );
		if(col&lt;=5) system(&quot;sleep 0.8&quot;); else if(col&lt;=10) system(&quot;sleep 0.3&quot;); else if(col&lt;=15) system(&quot;sleep 0.06&quot;); else if(col&gt;15) system(&quot;sleep 0.02&quot;);

		hanoi( tab, fil, col, disc-1, ultNum, A, O, D );
	};

};

main()
{
	int fil=3, col, *tablero = NULL;
	int f, c, disc=1, ultNum;

	printf( &quot;Indique el numero de discos: &quot; );
	scanf( &quot;%i&quot;, &amp;col );

	tablero = (int *)malloc( sizeof(int)*fil*col );

	// Resetea las torres poniendo &quot;los discos&quot; en una de ellas y 0 en el resto.
	for( f=0; f &lt; fil; f++ )
		for( c=col-1; c &gt;= 0; c-- )
			if( f==0 )
			{
				tablero[col*f+c] = disc;
				disc+=2;
			}
			else
				tablero[col*f+c] = 0;

	ultNum = disc;

	// Se imprime el tablero antes de iniciar ningún movimiento:
	system(&quot;clear&quot;);
	imprime( tablero, fil, col, ultNum );
	system(&quot;sleep 1&quot;);

	// Se llama a hanoi para comenzar &quot;la partida&quot;:
	hanoi( tablero, fil, col, col, ultNum, 0, 1, 2 );
};
</pre>
]]></content:encoded>
			<wfw:commentRss>http://giltesa.com/2012/01/25/5x07-torres-de-hanoi-parte2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

