CONTENIDO DE LA LECCIÓN 11
|
|
- Ignacio Espinoza Soriano
- hace 7 años
- Vistas:
Transcripción
1 CONTENIDO DE LA LECCIÓN 11 RECURSIVIDAD 1. Introducción 2 2. Ejemplos de recursividad Ejemplos 11.1, 11.2, 11.3, 11.4, 11.5, 11.6, 3 3. Funcionamiento interno de la recursividad Ejemplos 11.7, 11.8, 11.9, Soluciones no recursivas (iterativas) Ejemplos 11.10, 11.11, El problema de las Torres de Hanoi Ejemplo Uso de las pilas para simular recursividad El problema de las ocho reinas Ejemplo Casos interesantes Ejemplo 11.15: Información genealógica Ejemplo 11.16: Árboles similares Ejemplo 11.17: Árboles no similares Retroceso Programación no determinista Retroceso cronológico Retroceso de dependencia dirigida Uso de la recursividad Examen breve Lo que necesita saber Preguntas y problemas Preguntas Problemas
2 LECCIÓN 11 RECURSIVIDAD INTRODUCCIÓN Una función que se llama a sí mismo se dice que es recursiva. La recursividad en las funciones puede darse de dos maneras diferentes: a. Directa. La función se llama directamente a sí misma. Por ejemplo, observe la figura 11.1, funciona() es una función y en alguna parte de ella aparece una llamada a sí misma: funciona() Llamada a funciona() Figura Recursividad directa b. Indirecta. La función llama a otra función y esta a su vez llama a la primera. Por ejemplo, en la figura 11.2a la función funciona() llama a la función funcionb() y esta a su vez invoca a la primera; es decir el control regresa a funciona(). funciona() Llamada a funcionb() funcionb() Llamada a funciona() funciona() Llamada a funcionb() funcionb() Llamada a funcionc() funcionc() a) b) Figura Recursividad indirecta También se da la recursividad indirecta cuando una función llama a otra y ésta a una tercera. Una vez ejecutada, el control regresa a la función que la llamó, lo mismo sucede en todos los niveles. Por ejemplo, en la figura 11.2b la función funciona() llama a la función funcionb(), y esta llama a la función funcionc() Cuando funcionc() concluye, el control regresa a funcionb(); y al terminar ésta, el control se transfiere a funciona() 11-2
3 En toda definición recursiva de un problema se debe establecer un estado básico (estado primitivo, estado de salida o estado de terminación) Es decir, un estado en el cual la solución no se presente de manera recursiva sino directamente. Además la entrada (datos) del problema debe ir acercándose al estado básico. Si dada la definición de un problema es posible determinar el estado básico y el acercamiento paulatino al mismo, entonces se puede llegar a una solución. En otro caso se estaría en presencia de una definición circular del problema. Es importante comprender que cada instanciación (copia activa) de una función recursiva es totalmente peculiar y tiene sus propios argumentos, variables locales, direcciones de retorno, etc. Objetivos de esta lección: Comprender y manejar el concepto de recursividad. Aprender como se escriben y utilizan funciones que se llaman a sí mismas. Resolver problemas utilizando recursividad. Los ejemplos que aparecen a continuación, a pesar de que pueden resolverse de manera no recursiva permiten ilustrar claramente el concepto de recursividad. EJEMPLOS DE RECURSIVIDAD Ejemplo 11.1 Solución Escriba una función recursiva C++ para encontrar la suma de todos los enteros desde 1 hasta N. Piense en esta operación por un minuto. No es una operación recursiva clásica? Para encontrar la suma de enteros de 1 a 5, podría adicionar 5 a la suma de enteros de 1 a 4? Entonces, para encontrar la suma de 1 a 4, adiciona 4 a la suma de enteros de 1 a 3, y así sucesivamente, correcto? Expresada en símbolos: sumanumeros(5) = 5 + sumanumeros(4) sumanumeros(4) = 4 + sumanumeros(3) sumanumeros(3) = 3 + sumanumeros(2) sumanumeros(2) = 2 + sumanumeros(1) sumanumeros(1) = 1 Observe que sumanumeros(1) es el estado básico, porque su valor es conocido. Ahora, traduciendo este proceso a una función recursiva, se obtiene: sumanumero s( n) 1 n + sumanumeros( n 1) Si Si n = n > 1 1 Esta expresión se puede expresar en seudocódigo como sigue: 11-3
4 Ejemplo 11.2 sumanumeros(n) si (n == 1) entonces regresar (1). si no regresar ( n + sumanumeros(n-1)). La función C++ se codifica entonces directamente desde el algoritmo como: /************************************************************* Esta función recursiva calculará la suma de los enteros entre 1 hasta N *************************************************************/ int sumanumeros(int n) if(n == 1) return (1) else return (n + sumanumeros(n 1)) // Fin de sumanumeros() Algoritmo sumanumeros El siguiente programa: SUMAENT.CPP, muestra el uso del algoritmo 11.1 /* Este programa: SUMAENT.CPP, calcula la suma de los números enteros positivos comprendidos entre 1 y el número dado. */ #include <iostream.h> //Para cin y cout int sumanumeros(int n); void main(void) int n; /* Tener en cuenta que el valor devuelto es de la clase int. Por lo tanto la suma esta limitada a un máximo de 32767, en caso contrario se producirá un sobreflujo. */ cout << "Dame un número entero mayor que cero: "; cin >> n; cout << "\nla suma de los números enteros comprendidos entre 1 y " << n << " es: " << sumanumeros(n) << endl; int sumanumeros(int n) if(n == 1) return(1); else return(n + sumanumeros(n-1)); 11-4
5 Ejemplo 11.3 Factorial de un número: La notación n! se lee factorial de n e indica el producto de los enteros positivos desde 1 hasta n. Por ejemplo: 3! = ! = ! = n! = (n-2) (n-1) (n) También definimos 1! = 1 y 0! = 1. Si se le pide que desarrolle una función que calcule el factorial de un número, cómo le haría? Si invertimos la definición de la fórmula tenemos: n! = n (n-1) (n-2) Por lo tanto, 4! = Observe que es 3!; entonces, podemos definir 4! de manera recursiva como: En general, podemos definir n! como: 4! = 4 3! n! = n (n-1)! (n-1)! = (n-1) (n-2)! (n-2)! = (n-2) (n-3)!... Llegamos a definir entonces, el factorial de un número n en términos del factorial del número (n-1) de la siguiente manera: 1 n! = n ( n 1)! Si Si n = 0 n > 1 o n = 1 En la definición recursiva del factorial se da un estado básico (si n = 0 o n = 1, entonces el factorial vale 1), en el cual el problema ya no se define en términos de sí mismo sino que se asigna un valor directamente. En el paso recursivo de la fórmula se utiliza el concepto de factorial aplicado a (n-1) Por ser un número entero positivo será (n-1) un valor más cercano al estado básico (n = 0 o n = 1) Una vez establecida la definición recursiva de los números factoriales, podemos comenzar a formular un algoritmo recursivo. Considere el siguiente seudocódigo: factorial(n) INICIO x = n -1. calcular x!. // (n-1)! regresar(n x!). // n! = n (n -1)! FIN. La función factorial() estima el valor de n! calculando el valor de (n-1)! y luego multiplicando el resultado por n. Sin embargo, como ya habrá notado, la segunda instrucción no está definida de modo correcto: tenemos que encontrar una forma de calcular el valor de x!. Si lo piensa bien, verá que ya tenemos una: factorial() Esta función calcula el factorial de un número. Apliquemos este conocimiento y volvamos a escribir la rutina como: 11-5
6 factorial(n) INICIO x = factorial(n-1). // (n-1)! regresar(n x). // n! = n (n -1)! FIN. Ahora bien, cuando calcule el valor de n!, la función se llamará a sí misma de modo recursivo para estimar el valor de (n-1)!. Cabe preguntarnos si la función está completa. Mirémosla con detenimiento y analicemos su ejecución cuando calcula 2!. El procesamiento se inicia cuando se llama a la función con un argumento de 2. Entonces ésta calcula 2! recursivamente llamándose a sí misma con un argumento de 1; para estimar 1!, vuelve a llamarse a sí misma otra vez con un argumento de 0. La tercera copia (instancia) de la función se llamará a sí misma con un argumento de 1, la siguiente con 2, y así sucesivamente. El problema está más claro ahora: la función es recursiva hasta el infinito. Todas las funciones recursivas necesitan una forma de detenerse, a la que hemos denominado estado básico o primitivo. Se coloca, por lo común, en la parte superior de una función recursiva, y contiene instrucciones que al final terminan la recursividad y comienzan a desapilar todas las llamadas anidadas. Si se le omite o está incorrecta, como acabamos de ver, el funcionamiento puede convertirse en infinitamente recursivo. Volviendo a nuestro ejemplo, identifiquemos un estado básico para la función factorial(). Por definición, sabemos que 0! = 1 y que 1! = 1. Por lo tanto, podemos añadir revisiones para estos valores en la parte superior del procedimiento, de este modo: factorial(n) INICIO si(n == 0 o n == 1) regresar(1). FIN. regresar(n * factorial(n-1)). Ahora, cuando se le llame con un argumento de 0 o 1, la función devolverá un valor explícito en lugar de realizar otra llamada recursiva. (Observe que hemos eliminado la innecesaria variable temporal x de nuestro algoritmo) Pero aún tenemos otro problema. La función puede ser llamada al comienzo con un argumento negativo. Por lo tanto, debemos añadir una revisión más para asegurar que la función ha sido llamada de modo apropiado: factorial(n) INICIO si(n < 0) /* Revisa Argumentos erróneos */ regresar(-1). si(n == 0 n == 1) regresar(1). regresar(n * factorial(n-1)). FIN. A continuación se muestra la versión final escrita en C++. int factorialrecurrente(int n) if(n < 0) /* Revisa argumentos erróneos */ return(-1); 11-6
7 if(n == 0 n == 1) return(1); return(n * factorialrecurrente(n-1)); Algoritmo 11.2: factorialrecurrente Ejemplo 11.4 Serie de Fibonacci: Otro caso clásico de problemas definidos recursivamente es el cálculo de la serie de Fibonacci: 0, 1, 1, 2, 3, 5, 8, 13, 21,..., etc. Recuérdese que el Fibonacci de un número se obtiene de la suma de los dos números Fibonacci anteriores. A continuación se ilustrará el concepto de números Fibonacci: Por definición: Fibonacci(0) = 0 Fibonacci(1) = 1 Los demás números de la serie en base a la definición son: Fibonacci(2) = Fibonacci(1) + Fibonacci(0) = = 1 Fibonacci(3) = Fibonacci(2) + Fibonacci(1) = = 2 Fibonacci(4) = Fibonacci(3) + Fibonacci(2) = = 3 La definición en forma recursiva de la serie de Fibonacci será: n Fibonacci ( n) = fibonacci( n 1) + fibonacci( n 2) Si Sí ( n = 0) n > 1 o ( n = 1) En este ejemplo el estado básico se presenta cuando n es cero o es uno. En el paso recursivo de la fórmula se utiliza el concepto de Fibonacci aplicado a (n-1) y (n-2) Por ser n un número entero positivo serán (n-1) y (n-2) valores más cercanos al estado básico. Empecemos ahora a construir una solución recursiva: fibonaccirecursivo(n) INICIO si(n < 0) regresar(-1). /* Argumento erróneo */ si((n = 0) o (n == 1)) regresar(n). FIN. regresar(fibonaccirecursivo(n-1) + fibonaccirecursivo(n-2)). Esta solución tiene un error, la verificación n < 0, que busca un argumento erróneo, solo es válida la primera vez, en llamadas subsecuentes a la función no tiene sentido. Por lo tanto se hace necesario realizar algunas modificaciones al algoritmo anterior: fibonaccirecursivoinicial(n) INICIO si(n < 0) regresar(-1). /* Argumento erróneo */ 11-7
8 FIN. regresar(fibonaccirecursivo(n)). fibonaccirecursivo(n) INICIO si((n == 0) o (n == 1)) regresar(n). FIN. regresar(fibonaccirecursivo(n-1) + fibonaccirecursivo(n-2)). La versión en C++ del algoritmo anterior es: int fibonaccirecursivoinicial(n) if(n < 0) return(-1); return(fibonaccirecursivo(n)); int fibonaccirecursivo(n) if((n == 0) (n == 1)) return(n); return(fibonaccirecursivo(n - 1) + fibonaccirecursivo(n - 2)); Algoritmo 11.3: fibonaccirecursivo Ejemplo 11.5 El siguiente programa: FIBONA1.CPP, ilustra el uso del algoritmo /* El siguiente programa: FIBONA1.CPP, calcula los n términos de la serie de Fibonacci */ #include <iostream.h> //Para cout y cin int fibonaccirecursivoinicial(int n); int fibonaccirecursivo(int n); void main(void) int n; cout << "Dame el número de términos a calcular: "; cin >> n; cout << endl; while(n > 0) cout << "El valor del término " << n << " de la serie de Fibonacci es: " << fibonaccirecursivoinicial(n - 1) << endl; n = n - 1; 11-8
9 int fibonaccirecursivoinicial(n) if(n < 0) return(-1); return(fibonaccirecursivo(n)); int fibonaccirecursivo(n) if((n == 0) (n == 1)) return(n); return(fibonaccirecursivo(n - 1) + fibonaccirecursivo(n - 2)); Ejemplo 11.6 En este ejemplo presentamos el caso de una inversión en una institución bancaria. Se ha depositado un capital m por el cual se recibe un x% de interés anual. El problema consiste en determinar el capital que se tendrá al cabo de n años. Supóngase que m = $ y x = 10%, entonces: C 0 = 5000 C 1 = C 0 + C 0 * 10% C 2 = C 1 + C 1 * 10% [Capital Inicial] [Capital al finalizar el primer año de inversión] [Capital al finalizar el segundo año de inversión] En general, al cabo de n años se tendrá que: C n = C n-1 + C n-1 * 10% o C n = 1.10 * C n-1 Se llega a una definición recursiva del cálculo de inversiones. C n m = (1 + x)* C Sí n = 0 n 1 Sí n 0 > Nuevamente se cuenta con un estado básico, para n = 0, y un acercamiento a él en la otra expresión de la fórmula. El siguiente algoritmo presenta una solución recursiva del cálculo de una inversión: balance(n, m, x) FIN. INICIO si(n = 0) entonces regresar(m). //Estado básico sino regresar((1+x) * balance((n-1), m, x). Para simplificar el ejemplo: sí definimos el capital inicial m y la tasa x como variables globales; y la recapitalización es mensualmente tendremos: float balance(int m) if (n == 0) 11-9
10 return (m); else return((1 + x / 12 / 100) * balance(n 1)); //Fin de balance() Algoritmo 11.4: balance Esto es todo lo que hay que hacer! Esta función calculará al final de cualquier mes n que pase por la función. Observe cómo la función se llama a si misma en la cláusula else. Cuando la computadora encuentra la llamada recursiva en la cláusula else, deberá temporalmente retrasar el cálculo para evaluar la llamada de la función recursiva justo como se hizo el cálculo de interés compuesto. Cuando encuentra la cláusula else por segunda vez, la función se llama a sí misma otra vez y se mantiene llamándose cada vez que se ejecuta la cláusula else hasta que alcanza el estado primitivo. Cuando esto sucede, se ejecuta la cláusula if (porque n es cero), y la llamada recursiva termina. Ahora, insertaremos esta función en un programa llamado CAPITAL.CPP, para calcular el interés compuesto, como sigue: // Este programa: CAPITAL.CPP, ilustra el cálculo del interés compuesto de un capital inicial determinado #include <iostream.h> // Para cin y cout // Funciones prototipo y variables globales float balance(int); // Regresa nuevo balance float deposito = 0.0; // Capital inicial float tasa = 0.0; // Tasa de interés anual void main(void) // Define la variable argumento de la función int meses = 0; // Número de meses después del depósito // inicial para determinar el balance // Obtención del capital inicial, número de meses y tasa de interés cout << "Escriba el depósito inicial: $"; cin >> deposito; cout << "Escriba el número de meses (periodo): "; cin >> meses; cout << "Escriba la tasa de interés anual: "; cin >> tasa; // Establece la salida ajustada y la precisión cout.setf(ios::fixed); cout.precision(2); // Muestra resultados, haciendo la llamada a la función recursiva cout << "\n\ncon un depósito inicial de $" << deposito << " y una tasa de interés de " << tasa << "%\nel balance al final de " << meses << " meses deberá ser de $" << balance(meses) << endl; // Fin de main() 11-10
11 /*********************************************************************** Esta función recursiva calculará un balance de cuenta con base en una tasa de interés compuesto mensual. ************************************************************************/ float balance(int n) if(n == 0) return deposito; else return(1 + tasa / 12 / 100) * balance(n - 1); //Fin de balance() El programa anterior pide al usuario que escriba el depósito inicial, número de meses a calcular y la tasa de interés anual. Las variables deposito y tasa se definen en forma global para propósitos de ejemplo para que podamos concentrarnos en la función recursiva. El número de meses a calcular se pasa a la función como un parámetro por valor. Realmente las variables deposito y tasa podrían definirse en forma local para main() y pasar a la función como parámetros por valor. Esto se dejará como un ejercicio. Una vez que el usuario escribe los valores necesarios, se hace la llamada recursiva y el programa escribe el balance final. Aquí está una muestra de la salida del programa: Escriba el depósito inicial: $1000 Escriba el número de meses para calcular: 4 Escriba la tasa de interés anual: 12 Con un depósito inicial de $1000 y una tasa de interés de 12% el balance al final de 4 meses deberá ser de $ FUNCIONAMIENTO INTERNO DE LA RECURSIVIDAD Internamente se utiliza una estructura tipo pila para guardar los valores de las variables y constantes locales de la función que efectúa la llamada. De esta manera, una vez concluida la ejecución, se puede seguir con los pasos que quedaron pendientes recuperando los valores necesarios de la pila. Con cada llamada recursiva se crea una copia de todas las variables y constantes que estén vigentes, y se guarda esa copia en la pila. Además se guarda una referencia a la siguiente instrucción a ejecutar. Al regresar se toma la imagen guardada en el tope de la pila y se continúa operando. Esta acción se repita hasta que la pila quede vacía. Se tratará de ilustrar estos conceptos con ayuda de los ejemplos anteriores. Ejemplo 11.7 Retomando el problema del cálculo del factorial de un número n (véase el algoritmo 11.2), para mostrar el funcionamiento interno de la recursión. En la tabla 11.1 se presentan los valores que van adquiriendo las variables y los valores que son guardados en la pila, en el transcurso del cálculo del factorial de un número n = 4. PASO n PILA FactorialRecurrente *, 2 3 4*, 3*, 3 2 4*, 3*, 2*, 4 2 4*, 3*, 2* *, 3* 2(2*1) 6 3 4* 6(3*2) (4*6) Tabla Cálculo recursivo del factorial 11-11
12 En el primer paso n es igual a 4; por lo tanto, siguiendo el algoritmo 11.2 debe hacerse 4 * 3! Ante la imposibilidad de realizar esta operación (porque primero debe calcularse 3!) se guarda el valor de n en la pila y se continúa trabajando con n = 3. Con el nuevo valor de n procedemos de manera similar que con n = 4. La diferencia radica en que la entrada, n, está más cercana al estado básico. En consecuencia, en el paso 2 se agrega el valor 3 a la pila para multiplicarlo posteriormente por 2! En el paso 3 se agrega el valor 2 a la pila. Una vez alcanzado el estado básico, paso 4, se comienza a extraer los valores almacenados en la pila y a operar con ellos. En el paso 5 se extrae de la pila el valor 2 y se multiplica por el factorial de 1, obteniendo 2! Luego se extrae el 3 y se multiplica por el factorial de 2, para obtener 3! Se continúa así hasta que la pila quede vacía, lo cual ocurre en el paso 7 donde se calcula el factorial de 4. En la figura 11.3 se presenta gráficamente lo descrito anteriormente. factorialrecurrente(4) = 24 4 * factorialrecurrente(3) = * factorialrecurrente(2) = * factorialrecurrente(1) 1 = Ejemplo 11.8 Figura Representación gráfica de la recursividad Retomando ahora el problema del cálculo de un número Fibonacci n (véase el algoritmo 11.3), para mostrar nuevamente el funcionamiento interno de la recursividad. En la tabla 11.2 se presentan los valores que van adquiriendo las variables y los valores almacenados en la pila, durante el cálculo del número Fibonacci n = 4. PASO n PILA FibonacciRecursivo fibonaccirecursivo(2) +, 2 3 fibonaccirecursivo(2) +, fibonaccirecursivo(1) +, 3 2 fibonaccirecursivo(2) +, fibonaccirecursivo(1) +, fibonaccirecursivo(0) +, 4 1 fibonaccirecursivo(2) +, fibonaccirecursivo(1) +, 1 fibonaccirecursivo(0) +, 5 0 fibonaccirecursivo(2) +, fibonaccirecursivo(1) +, 1(1+0) 6 1 fibonaccirecursivo(2) +, 2(1+1) 7 2 fibonaccirecursivo(0) +, fibonaccirecursivo(0) +, 3(2+1) 9 0 3(3+0) Tabla Cálculo recursivo de un número Fibonacci 11-12
13 En la misma podemos observar que en este ejemplo se van guardando en la pila llamadas recursivas pendientes de ejecución. Para n igual a 4 se llama al proceso fibonaccirecursivo(3) y se guarda en la pila fibonaccirecursivo(2), paso 1. En el paso 2 se calcula fibonaccirecursivo(3), llamando al proceso fibonaccirecursivo(2) y almacenando en la pila fibonaccirecursivo(1) (una vez calculados, serán sumados) Se continúa de esta manera para los diferentes valores de n, hasta que éste sea 1 o 0. Cuando n es igual a 1, paso 4, se asigna directamente un valor a fibonaccirecursivo(1), ya que éste es un estado básico. Como se llegó a un estado básico, se comienzan a extraer sucesivamente de la pila los elementos dejados en ella. En el paso 5 se extrae de la pila a fibonaccirecursivo(0), el cual también tiene solución directa por ser un estado básico y se suma al número fibonacci obtenido en el paso anterior. Lo mismo sucede en el paso 6 al extraer fibonaccirecursivo(1) En el paso 7, al extraer fibonaccirecursivo(2) se procede de igual manera que en el paso 3. Es decir se llama a fibonaccirecursivo(1) y se almacena en la pila a fibonaccirecursivo(0) El proceso continúa hasta que la pila quede vacía, paso 9. En la figura 11.4 se presenta gráficamente lo descrito con anterioridad
14 fibonaccirecursivo(4) = fibonaccirecursivo(3) + fibonaccirecursivo(2) = 3 MIGUEL Á. TOLEDO MARTÍNEZ fibonaccirecursivo(3) = fibonaccirecursivo(2) + fibonaccirecursivo(1) = 2 fibonaccirecursivo(2) = fibonaccirecursivo(1) + fibonaccirecursivo(0) = 1 fibonaccirecursivo(1) = fibonaccirecursivo(0) = fibonaccirecursivo(1) = fibonaccirecursivo(2) = fibonaccirecursivo(1) + fibonaccirecursivo(0) = 1 fibonaccirecursivo(1) = fibonaccirecursivo(0) = Figura Representación gráfica de la recursividad 11-14
15 Ejemplo 11.9 Para concluir esta serie de ejemplos sobre el funcionamiento interno de la recursividad, retomemos el problema del cálculo de una inversión en una institución bancaria (véase el algoritmo 11.4). En la tabla 11.3 se presentan los valores que van adquiriendo las variables y los valores almacenados en la pila, en el transcurso del cálculo de una inversión durante 4 años, con un capital inicial de $ y a un interés anual del 10%.(Nuevamente, para simplificar supondremos que los intereses se acumulan anualmente). PASO n PILA balance *, *, 1.10 *, *, 1.10 *, 1.10 *, *, 1.10 *, 1.10 *, 1.10 *, *, 1.10 *, 1.10 *, 1.10 *, *, 1.10 *, 1.10 *, 5500(5000 * 1.10) *, 1.10 *, 6050(5500 * 1.10) *, 6655(6050 * 1.10) (6655 * 1.10) Tabla Cálculo recursivo de una inversión bancaria En el primer paso n es igual a 4, por lo tanto siguiendo el algoritmo debe hacerse 1.10 por el capital obtenido durante la inversión de los 3 años anteriores. Como no se dispone de este valor, se almacena 1.10 en la pila para operar con él posteriormente y se continúa con el cálculo de balance(3), paso 2. Como no se tiene aún el estado básico se procede de manera similar al paso anterior, es decir se almacena 1.10 en la pila y se llama a balance(2). Se continúa así hasta llegar al estado básico, paso 5, en el cual el capital a utilizar en el cálculo de la inversión es el inicial, y por lo tanto puede ser asignado directamente. En el paso 6 se extrae de la pila el valor 1.10 y se multiplica por el capital, calculando así la inversión obtenida al cabo de un año. Se continúa realizando esta operación mientras haya elementos en la pila. En el paso 9 la pila queda vacía y así se obtiene, finalmente, el monto total de la inversión al cabo de 4 años. En la figura 11.5 se presenta gráficamente lo antes descrito. En esta sección se ha presentado el funcionamiento interno de la recursividad. Aunque es un proceso transparente al usuario, es muy importante conocerlo para comprender debidamente la herramienta que se está utilizando. También se ha mencionado en los párrafos anteriores que la recursividad es un instrumento poderoso para definir objetos en términos de sí mismos. Usando recursividad es posible escribir un código más compacto y, en ciertos casos, de más fácil comprensión. Sin embargo, debe quedar claro que la recursividad no da mayor rapidez a la ejecución del código y tampoco permite ahorrar espacio de memoria. Con respecto a este último punto debe tenerse en cuenta que la recursividad, para su funcionamiento utiliza una pila interna la cual consume memoria. En general, es recomendable usar recursividad cuando el problema por su naturaleza así lo exige. Es decir, cuando la solución simplifica y facilita de modo notable usando esta herramienta. En otro caso es más conveniente, computacionalmente hablando, utilizar alguna técnica iterativa para resolver el problema. Los casos que se presentaron antes, resueltos por algoritmos recursivos, son problemas que pueden resolverse fácilmente de manera iterativa. Ahora es preciso ejemplificar cada uno de estos problemas, con su correspondiente solución iterativa
16 balance(4) = * balance(3) = * balance(2) = * balance(1) = * balance(0) = Figura Representación gráfica de la recursividad SOLUCIONES NO RECURSIVAS (ITERATIVAS) Ejemplo Basándose en el algoritmo 11.2: factorialrecurrente antes diseñado, elaboraremos un algoritmo no recursivo. factorialiterativo(n) /* Este algoritmo calcula el factorial de un número n donde n es un valor numérico entero, positivo o nulo. */ INICIO si(n < 0) entonces regresar(-1). // Valida datos erróneos. factorial = 1. mientras (n > 0) hacer // Ciclo para calcular n! Inicio factorial = n * factorial. n = n-1. Fin. FIN. regresar(factorial)
17 Ejemplo La tabla 11.4 representa los valores que van adquiriendo las variables, durante el cálculo del factorial de un número n = 4. n factorial Tabla Cálculo iterativo del factorial A continuación se presenta un algoritmo no recursivo para el cálculo de los números de Fibonacci. fibonacciiterativo(n) /* Este algoritmo calcula el número Fibonacci correspondiente a n, donde n es un valor numérico entero, positivo o nulo. */ INICIO si((n = 0) o (n == 1)) entonces regresar(n).. si no Inicio fiba = 0. fibb = 1. i = 2. Fin. mientras(i <=n) Inicio Fin. fibo = fiba + fibb. fiba = fibb. fibb = fibo. i = i + 1. regresar(fibo). FIN. La tabla 11.5 representa los valores que van adquiriendo las variables, durante el cálculo del número Fibonacci n = 4. n fibo fiba fibb i Tabla Cálculo iterativo de un número Fibonacci A continuación presentamos un algoritmo con algunas variaciones respecto a la solución antes propuesta. Nuestro objetivo ahora es diseñar primero una función iterativa que acepte un número entero que no sea negativo como el argumento n y devuelva el valor F(n) La primera versión de nuestro seudocódigo puede ser así: 11-17
18 fibonacci(n) INICIO si (n = 0) regresar(0). si(n = 1) regresar(1). para i = 2 hasta n Inicio elementosiguiente = elementoanteanterior + elementoanterior. actualizar elementoanteanterior y elementoanterior. Fin. FIN. regresar(elementosiguiente). Observe que nuestro seudocódigo carece de algunos detalles relevantes: los valores iniciales de las variables, los incrementos para las variables que iteran (ciclos) y una prueba para detectar los argumentos válidos. Después de agregar esas instrucciones, el algoritmo queda así: fibonacci(n) INICIO si(n < 0) regresr(-1). si (n = 0) regresar(0). si(n = 1) regresar(1). elementoanteanterior = 0. elementoanterior = 1. para i = 2 hasta n Inicio elementosiguiente = elementoanteanterior + elementoanterior. ElementoAnteAnterior = elementoanterior. elementoanterior = elementosiguiente. Fin. FIN. regresar(elementosiguiente). Observe que hemos establecido la convención de devolver 1 para indicar un argumento erróneo. También observe que ya inicializamos y actualizamos las dos variables: elementoanteanterior y elementoanterior. Finalmente escribiremos un programa en C++ que llame a esta función. El programa se llamará FIBONA2.CPP
19 /* Este programa: FIBONA2.CPP, resuelve en forma iterativa la serie de Fibonacci */ #include <iostream.h> const int MAXIMO = 10; //Para cout //Máximo n int fibonacci(int n); void main(void) for(int i = -1; i <= MAXIMO; i++) cout << "\ti: " << i << " fib(" << i << "): " << fibonacci(i) << endl; int fibonacci(int n) int i; int elementosiguiente, elementoanteanterior, elementoanterior; if(n < 0) return(-1); if(n == 0) return(0); if(n==1) return(1); elementosiguiente = 0; elementoanteanterior = 0; elementoanterior = 1; for(i = 2; i <= n; i++) elementosiguiente elementoanteanterior elementoanterior = elementoanterior + elementoanteanterior; = elementoanterior; = elementosiguiente; return(elementosiguiente); Ejemplo Algoritmo no recursivo para el cálculo del capital obtenido en una inversión bancaria durante n años. balanceiterativo(n, m, x) /* Este algoritmo calcula el capital que se tendrá luego de invertir un capital inicial m, durante n años, con una tasa anual de x%. */ INICIO capital = m. i = 1. mientras(i <= n) hacer Inicio capital = capital + x * capital. i = i
20 Fin. FIN. regresar(capital). La tabla 11.6 presenta los valores que van adquiriendo las variables, en el transcurso del cálculo de una inversión durante 4 años con un capital inicial de $ a un interés anual del 10%. n m x capital i Tabla Cálculo iterativo de una inversión bancaria EL PROBLEMA DE LAS TORRES DE HANOI El problema de las Torres de Hanoi es un problema clásico de recursividad, ya que pertenece a la clase de problemas cuya solución se simplifica notablemente al utilizar recursividad. Tenemos tres torres: A, B y C, y un conjunto de cinco discos, todos de distintos tamaños. El enigma comienza con todos los discos colocados en la torre A de tal forma que ninguno de ellos cae sobre uno de menor tamaño; es decir, están apilados, uno sobre otro, con el más grande hasta abajo, encima de él el siguiente en tamaño y así sucesivamente (véase la figura 11.6, donde se muestra un ejemplo) El propósito del enigma es apilar los cinco discos, en el mismo orden, pero en la torre C. Durante la solución, puede colocar los discos en cualquier torre, pero debe apegarse a las siguientes reglas: Sólo puede mover el disco superior de cualesquiera de las torres. Un disco más grande nunca puede estar encima de uno más pequeño. Torre A Torre B Torre C Figura 11.6 Enigma de Las torres de Hanoi Intente resolver manualmente el enigma con una cantidad pequeña de discos, digamos cinco o seis, antes de proseguir con la solución algorítmica. El problema que enfrentamos es cómo escribir un programa que resuelva el enigma para cualquier cantidad de discos. Comencemos por considerar una solución general para n discos. Si tenemos la solución para n-1 discos, sería evidente que podemos resolver el problema para n discos: resolvemos el enigma para n-1 discos y luego movemos el disco n a la torre C. De modo 11-20
21 similar, si pudiéramos resolver para n-2 discos, el caso n-1 sería más sencillo. Podemos continuar de esta manera hasta llegar al caso trivial donde n = 1: simplemente movemos el disco de la torre A a la torre C. Aunque no sea obvio, lo que acabamos de describir es una solución recursiva para el problema, es decir, resolvimos el problema para una n dada en términos de n-1. Examinemos un ejemplo concreto y resolvamos el enigma con cinco discos. Supongamos que sabemos cómo resolverlo con cuatro discos, moviéndolos de la torre A a la torre B (utilizando C como torre auxiliar) Luego, para terminar la solución, sólo debemos mover el disco más grande de la torre A a la torre C y mover los cuatro discos de la torre B a la torre C (usando A como auxiliar). Podemos resumir la solución de un modo más preciso: 1. Si n = 1, movemos el disco de A a C y nos detenemos. 2. Movemos n-1 discos de A a B utilizando C como auxiliar. 3. Movemos el disco n de A a C. 4. Movemos n-1 discos de B a C usando A como auxiliar. Observe que los pasos 2 y 4 son recursivos porque nos sugieren que repitamos la solución para n-1 discos. También observe que las torres cambian su papel conforme avanza la solución. Ahora que comprendemos la solución, debemos convertir estas reglas en un algoritmo. Diseñaremos una función, llamada torres(), que mostrará los movimientos necesarios para resolver el enigma de acuerdo con un número dado de discos. Su salida estará constituida por comandos de este tipo: Mueve disco X de torre Y a la torre Z La función torres() necesita cuatro argumentos. El primero indica la cantidad de discos que se van a usar. Los otros tres determinan el papel que tendrán las tres torres: origen, destino y auxiliar. A continuación se muestra el seudocódigo que soluciona el enigma de Las torres de Hanoi. Observe cómo la rutina cambia el papel de cada torre con cada llamada recursiva. Sin embargo, la función carece de un detalle importante: no revisa valores erróneos que le fueron pasados como argumentos. Dejaremos esto como ejercicio. torres(entero n, carácter A, carácter B, carácter C) /* n: Cantidad de discos */ /* A: torre origen */ /* B: torre auxiliar */ /*C: torre destino */ INICIO si(n == 1) Inicio escribir( mueve disco, n, de la torre, A, a la torre, C). regresa. Fin. /* Mueve n-1 discos de la torre A a la torre B (C es e la torre auxiliar) */ torres(n-1, A, C, B). /* Mueve el enésimo aro de la torre A a la torre C */ escribir( mueve disco, n, de la torre, A, a la torre, C)
22 /* Mueve n-1 discos de la torre B a la torre C (A es la torre auxiliar) torres(n-1, B, A, C). FIN. regresar. Algoritmo 11.5: Torres El algoritmo recursivo anterior ofrece una solución clara y compacta al problema de las Torres de Hanoi. Es posible dar una solución iterativa a este problema, pero es conveniente mencionar que la misma es más complicada y extensa. Ejemplo El siguiente programa: HANOI.CPP, ilustra el uso del algoritmo Torres /* Este programa: HANOI.CPP, muestra el algoritmo para resolver el enigma de Las torres de Hanoi. */ #include <iostream.h> //Para cout y cin void torres(int n, char A, char B, char C); void main(void) int discos; char origen char auxiliar char destino = 'A'; = 'B'; = 'C'; cout << "Dame el número de discos: "; cin >> discos; cout << endl; torres(discos, origen, auxiliar, destino); void torres(int n, char A, char B, char C) /* n: Cantidad de discos */ /* A: torre origen */ /* B: torre auxiliar */ /*C: torre destino */ if(n == 1) cout << "Mueve disco " << n << " de la torre " << A << " a la torre " << C << endl; return; /* Mueve n-1 discos de la torre A a la torre B (C es la torre auxiliar) */ torres(n-1, A, C, B); /* Mueve el enésimo disco de la torre A a la torre C */ cout << "Mueve disco " << n << " de la torre " << A << " a la torre " << C << endl; /* Mueve n-1 discos de la torre B a la torre C (A es la torre auxiliar) */ torres(n-1, B, A, C); return; 11-22
23 Luego de realizar algunas pruebas, para distintos valores de n, se puede concluir que, para cualquier n, el número de movimientos está dado por la siguiente fórmula: numeromovimientos = 2 n -1 En la siguiente sección se estudiará cómo pueden plantearse soluciones no recursivas a problemas definidos en forma recursiva, usando pilas. USO DE LAS PILAS PARA SIMULAR RECURSIVIDAD Se ha presentado a la recursividad como una herramienta poderosa para crear algoritmos claros y concisos para problemas que se definen en términos de sí mismos. También se ha mencionado que el uso de la recursividad puede ser costoso en lo que a espacio de memoria se refiere. Por todo lo dicho y además, en consideración de que muchos lenguajes de programación no cuentan con esta facilidad, resulta conveniente contar con algún procedimiento que permita simular la recursividad. Una función puede tener variables locales y parámetros (argumentos) Cuando se hace una llamada recursiva a la función, los valores actuales de las variables y parámetros deben conservarse. Igualmente debe conservarse la dirección a la cual debe regresar el control una vez ejecutado la función llamada. En la función que se propone para simular recursividad sólo se conservan los valores de las variables y parámetros. Para ello se utilizan pilas. Nuevamente aparece el concepto de pila relacionado con recursividad. Una aplicación de éstas se estudió cuando se analizó la operación interna de la recursividad. Otra aplicación importante es el centro de atención de esta sección: simulación de recursividad mediante el uso de pilas. A continuación se presenta el problema de la Torres de Hanoi, pero con un enfoque no recursivo. Se verá cómo se puede modificar el algoritmo antes presentado para obtener una versión no recursiva del mismo. El algoritmo 11.5: Torres, trabaja con cuatro parámetros: n, origen, destino, auxiliar (el número de discos y los nombres de las tres torres que intervienen en el problema) Si se quieren conservar los valores de estos parámetros en cada llama, se deberá definir una pila para cada uno de ellos. (Otra alternativa sería definir una pila única, en la que cada elemento de la misma fuera capaz de almacenar los cuatro parámetros) Aquí se definirán cuatro pilas de trabajo: pilan: para almacenar imágenes de n. pilao: para almacenar imágenes de origen. pilad: para almacenar imágenes de destino. pilax: para almacenar imágenes de auxiliar. También será necesario manejar un tope para cada una de las pilas. El algoritmo siguiente es una solución iterativa al problema de las Torres de Hanoi. hanoiiterativo(n, origen, destino, auxiliar) INICIO /* Este algoritmo resuelve el problema de las torres de Hanoi de manera no recursiva. origen, destino y auxiliar son variables que almacenan los nombres de las tres torres, n representa el número de discos
24 pilan, pilao, pilad y pilax son estructuras de datos tipo pila. tope es una variable de tipo entero. varaux es una variable de tipo carácter. bandera es una variable de tipo booleano. */ tope = 0. bandera = falso. mientras(n > 0) Y (bandera = falso) Inicio mientras(n > 1) Inicio /* Guardar en las pilas los valores actuales de los parámetros. */ tope = tope + 1. pilan[tope] = n. pilao[tope] = origen. pilad[tope] = destino. pilax[tope] = auxiliar. /* Simular llamada a Hanoi con n-1, origen, auxiliar y destino. */ Fin. n = n 1. varaux = destino. destino = auxiliar. auxiliar = varaux. FIN. Fin. escribir( Mover un disco de, origen, a, destino). bandera = verdadero. si(tope > 0) entonces // Las pilas no están vacías. Inicio // Se extraen los elementos de tope de las pilas. n = pilan[tope]. origen = pilao[tope]. destino = pilad[tope]. auxiliar = pilax[tope]. tope = tope 1. Fin. escribir( Mover un disco de, origen, a, destino). /* Simular llamada a Hanoi con n 1, auxiliar, destino y origen. */ n = n 1. varaux = origen. origen = auxiliar. auxiliar = varaux. bandera = falso. Algoritmo 11.6: hanoiiterativo 11-24
25 A continuación se presenta un conjunto de tablas donde se analiza el algoritmo 11.6: hanoiiterativo para diferentes valores de n. Todas las tablas tienen las mismas columnas y éstas representan lo siguiente: C1: representa el parámetro origen. C2: representa el parámetro destino. C3: representa el parámetro auxiliar. C4: representa la variable tipo pilan. C5: representa la variable tipo pilao. C6: representa la variable tipo pilad. C7: representa la variable tipo pilax C8: representa los movimientos de disco entre dos torres. Los escribiremos [x:y], y se interpretarán como que un disco ha sido movido de la torre x a la torre y. C9: representa la variable de control bandera, la cual puede tomar los valores de v (verdadero) y f (falso). En la tabla 11.7 se expone un seguimiento del algoritmo para n = 1. Paso N C1 C2 C3 tope C4 C5 C6 C7 C8 C9 0 1 A B C 0 Falso 1 [A:B] Verdadero Tabla Solución iterativa del problema de las torres de Hanoi. En el paso 1 se escribió el movimiento necesario para alcanzar el estado final (C8), y se asignó a la variable de control el valor verdadero (C9) Como una de las dos condiciones evaluadas en el algoritmo es falsa, hemos llegado a la solución del problema. En la tabla 11.8 se presenta un seguimiento del algoritmo 11.6: hanoiiterativo para n = 2. Paso n C1 C2 C3 tope C4 C5 C6 C7 C8 C9 0 2 A B C 0 Falso A B C 2 1 A C B 3 [A:C] Verdadero 4 2 A B C 0 [A:B] 5 1 C B A Falso 6 [C:B] Verdadero Tabla Solución iterativa del problema de las Torres de Hanoi En el primer paso se guarda en las pilas (C4, C5, C6 y C7) una imagen de los datos (n, origen, destino y auxiliar) Se preparan las variables para realizar el movimiento de los (n 1) discos superiores de la torre origen a la torre auxiliar (C1, C2 y C3), paso 2. En el paso 3 se escribe el movimiento de la torre origen a la torre destino (C8) En el paso 4 se extraen los elementos del tope de las pilas y se asignan a sus correspondientes variables (n, C1, C2 y C3), con lo que se recuperan los valores almacenados en ellas en el paso 1. Se escribe también el movimiento de la torre origen a la torre destino (C8) En el paso 5 se preparan las variables para realizar el movimiento de los (n 1) discos superiores de la torre auxiliar a la torre destino (C1, C2 y C3) En el paso 6 se realizó el último movimiento de disco, necesario para alcanzar el estado solución (C8) 11-25
26 En la tabla 11.9 se presenta un seguimiento del algoritmo 11.6: hanoiiterativo para n = 3. Paso n C1 C2 C3 tope C4 C5 C6 C7 C8 C9 0 3 A B C 0 Falso A B C 2 2 A C B A C B 4 1 A B C 5 [A:B] Verdadero 6 2 A C B 1 [A:C] 7 1 B C A Falso 8 [B:C] Verdadero 9 3 A B C 0 [A:B] 10 2 C A B Falso C B A 12 1 C A B 13 [C:A] Verdadero 14 2 C B A 0 [C:B] 15 1 A B C Falso 16 [A:B] Verdadero Tabla Solución iterativa del problema de las Torres de Hanoi Una simple comparación entre los métodos recursivos e iterativos permite concluir que la solución recursiva del problema de las Torres de Hanoi es mucho más compacta y más fácil de comprender que la solución no recursiva. De cualquier manera es importante contar con un formalismo para traducir procesos recursivos en procesos no recursivos, porque, como ya se mencionó más arriba, algunos lenguajes no tienen esta herramienta de programación y además en ciertos problemas, el costo de usar recursividad es significativo. EL PROBLEMA DE LAS OCHO REINAS Otro ejemplo clásico de programación recursiva es el enigma de Las ocho reinas (o damas) El problema es colocar ocho reinas en un tablero de ajedrez de tal forma que ninguna ataque a las demás. En ajedrez una reina puede comerse a cualquier pieza desplazándose cualquier cantidad de casillas (escaques) por una fila, una columna o en diagonal( véase la figura 11.7). Por lo tanto, el dilema es colocar las ocho reinas en un tablero 8 x 8 sin que compartan la misma fila, columna o diagonal. Intente resolver manualmente el enigma antes de continuar. Para comenzar nuestra solución, vamos a suponer que desarrollamos el procedimiento reina(), que intentará colocar una reina en una fila mediante su propio parámetro fila. De este modo la función analizará todos los escaques de la fila especificada y, tras localizar uno que no esté bajo ataque, colocará la reina ahí; luego ella misma se llamará de modo recursivo para colocar otra reina en la siguiente fila. Si puede colocar las ocho reinas en el tablero, la función devolverá el valor RESUELTO. Si todos los escaques de la fila indicada están bajo ataque, entonces devolverá FALLO. Comencemos a esbozar el algoritmo (observe que para facilitar la programación, las filas y las columnas se indexarán de 0 a 7) 11-26
27 reina(fila) INICIO para i = 0 hasta i < 8 i incrementado en 1 //Revisa cada columna si (asalvo(fila, i) //Prueba escaque Inicio Colocar la reina en el tablero: fila, i. si(reina(fila+1) == RESUELTO) regresa RESUELTO. FIN. Fin. regresa(fallo). //Todos los escaques están bajo ataque R Figura 11.7 Filas, columnas y diagonales de ataque de la reina. Es evidente que la descripción está incompleta. Primero, necesitamos una condición para detener la recursión. Pensemos en esto unos instantes. Sabemos que, por definición, hay un máximo de ocho reinas en el enigma. Por lo tanto, podemos revisar fila > 7 desde el comienzo de la función; Pero reflexionemos un momento en la importancia del valor que contiene el argumento fila. Si hacemos una llamada recursiva a reina() con fila equivalente a un valor n, significa que hemos resuelto de la fila 0 a la fila n-1. Por lo tanto, si debemos llamar a reina() cuando fila = 8, significa que todas las demás reinas (filas 0 a 7) ya fueron colocadas y la función debe devolver el valor RESUELTO. Después necesitamos una forma de registrar la posición de las reinas a medida que procede la función. Para hacerlo, utilizaremos un arreglo de caracteres de 8 x 8, que hará las veces de tablero. En cada posición, guardaremos (con propósito de mostrarlo) uno de los siguientes caracteres: - (guión) para indicar un escaque vacío; * (asterisco) para señalar un escaque donde se encuentra una reina. Por último, debemos definir la función asalvo(), que determina si un escaque específico está bajo ataque. Pero pospongamos el análisis de asalvo() hasta que no terminemos de definir reina() Incorporemos los cambios que hemos sugerido y veamos cómo toma forma nuestra función: 11-27
28 reina(fila) INICIO si(fila > 7) regresa(resuelto). //Estado de salida FIN. //Revisa cada columna: de 0 a 7 para i = 0 hasta i < 8 en incrementos de uno en uno de i //Verifica si el escaque esta o no bajo ataque si(asalvo(fila, i)) Inicio //Coloca la reina en el tablero tablero[fila][i] = REINA. //Prueba la fila siguiente si(reina(fila + 1) = RESUELTO regresa(resuelto). si no tablero[fila][i] = VACIA. Fin. regresa(fallo). Algoritmo 11.7: reina Observe que hemos añadido la instrucción: tablero[fila][i] = VACIA. porque si alguna llamada recursiva a reina() falla en encontrar una solución (con una reina ubicada en esa posición), esta instrucción restaura el tablero a su estado anterior; Luego la función queda en libertad para revisar el siguiente escaque disponible. Nuestro algoritmo empieza a tomar forma, por lo que ahora debemos analizar cómo implementar la función asalvo() El problema que debemos plantear es cómo determinará la función si un escaque específico está bajo ataque de una reina colocada con anterioridad. Primero, observe que, en realidad, no es necesario revisar posibles ataques a lo largo de las filas. Gracias a nuestra implementación, podemos tener la certeza de que la única reina que puede permanecer en una fila es la que intentamos colocar. Además, la revisión de ataques desde las columnas puede hacerse de modo directo, burdamente, indexando el tablero junto con la columna que vamos a revisar. Los ataques diagonales son los más difíciles de resolver. Como se ilustra en la figura 11.8, una reina colocada en cualesquiera de los escaques rojos sería atacada por la reina colocada en el escaque [3,3] Qué tan fácil podemos determinar si un escaque está bajo ataque a lo largo de sus dos diagonales (ascendente y descendente)? 11-28
29 R Figura 11.8 Ataques diagonales Diagonal ascendente Diagonal descendente Si mira con atención el tablero de la figura 11.8, observará que cada diagonal puede identificarse de modo único como una función de sus índices. Por ejemplo, examinemos la figura 11.9a. La suma de los índices (fila + columna) de cada escape en la diagonal ascendente es igual a 6. Por lo tanto, cualquier reina que haya sido colocada antes en un escaque cuyos índices sumen 6 estará bajo el ataque de la casilla [3,3] De modo similar, podemos derivar un valor único para las diagonales descendentes (véase la figura 11.9b.) restando los índices (columna fila). Observe que cada una de las 15 diagonales ascendentes tienen un intervalo de valores que va de 0 a 14, y las diagonales descendentes uno de 7 a R Figura 11.9a Diagonal Ascendente Figura 11.9b Diagonal descendente Podemos integrar este concepto en nuestra función asalvo() La idea es que cada vez que coloquemos una reina en el tablero actualicemos dos arreglos: uno que registre la diagonal ascendente y otro la descendente. El índice de cada arreglo será el valor de índice de cada diagonal (por comodidad para programar, sumaremos 7 al valor del índice de la diagonal descendente) Así, asalvo() sólo necesita revisar el arreglo de escaques apropiado para determinar si uno de éstos está bajo ataque desde alguna de sus diagonales. Debemos extender esta idea para rastrear ataques a lo largo de las columnas. En este caso, sólo usamos el valor de la columna como índice en el tercer arreglo
30 Ejemplo A continuación se muestra la solución completa del enigma, mediante el programa REINAS.CPP. Este programa conduce la rutina; inicializa el tablero y los arreglos de las banderas; luego llama a reinasiguiente() para que resuelva el enigma. Si esta última función devuelve RESUELTO, REINAS.CPP también llama a muestratablero() para que imprima la solución. /* Estre programa: REINAS.CPP, resuelve el problema de ubicar 8 reinas dentro de un tablero de ajedrez, sin que se ataquen la una con la otra. */ #include <iostream.h> #define FALLO 0 #define RESUELTO 1 #define VACIO '-' #define REINA '*' /* Banderas para revisar filas y diagonales */ char columnas[8]; char diagonalascendente[15]; char diagonaldescendente[15]; char tablero[8][8]; int reinasiguiente(int fila); void ponerbanderas(int fila, int columna); void restablecerbanderas(int fila, int columna); int asalvo(int fila, int columna); void muestratablero(); void main(void) int i, j; /* Inicializa tablero y banderas */ for(i = 0; i < 8; i++) for(j = 0; j < 8; j++) tablero[i][j] = VACIO; for(i = 0; i < 15; i++) diagonalascendente[i] = VACIO; diagonaldescendente[i] = VACIO; for(i = 0; i < 8; i++) columnas[i] = VACIO; /* Intenta resolver el problema de las ocho reinas */ if(reinasiguiente(0) == RESUELTO) muestratablero(); else cout << " No se hallaron soluciones!" << endl; 11-30
UNIVERSIDAD DE LOS ANDES NUCLEO UNIVERSITARIO RAFAEL RANGEL (NURR) DEPARTAMENTO DE FISICA Y MATEMATICA AREA COMPUTACION TRUJILLO EDO.
UNIVERSIDAD DE LOS ANDES NUCLEO UNIVERSITARIO RAFAEL RANGEL (NURR) DEPARTAMENTO DE FISICA Y MATEMATICA AREA COMPUTACION TRUJILLO EDO. TRUJILLO Recursividad: La recursividad es una técnica de programación
Más detallesProgramación II Recursividad Dr. Mario Rossainz López
5. RECURSIVIDAD 5.1. Introducción La recursividad es una técnica en la que una función o método se hace llamadas a sí misma en el proceso de la realización de sus tareas. La recursividad da al programador
Más detalles4.1 Definición. Se dice que algo es recursivo si se define en función de sí mismo o a sí mismo. Un objeto (problemas, estructuras de datos) es
Recursividad 4.1 Definición. Se dice que algo es recursivo si se define en función de sí mismo o a sí mismo. Un objeto (problemas, estructuras de datos) es recursivo si forma parte de sí mismo o interviene
Más detallesUNIVERSIDAD AUTÓNOMA CHAPINGO DPTO. DE PREPARATORIA AGRÍCOLA ÁREA DE FÍSICA RECURSIÓN. Guillermo Becerra Córdova
UNIVERSIDAD AUTÓNOMA CHAPINGO DPTO. DE PREPARATORIA AGRÍCOLA ÁREA DE FÍSICA RECURSIÓN Guillermo Becerra Córdova E-mail: gllrmbecerra@yahoo.com OBJETIVOS: Este trabajo tiene por objetivo mostrar las características
Más detallesTema 7: Recursividad
Tema 7: Recursividad Objetivos: en este tema estudiaremos funciones recursivas; esto es, funciones que se invocan a sí mismas. Estas funciones son equivalentes a estructuras tipo bucle pero permiten especificar
Más detallesRecursividad. Definición de Recursividad: Técnica de programación muy potente que puede ser usada en lugar de la iteración.
Capítulo IV Recursividad Aprende a nacer desde el dolor y a ser más grande que el más grande de los obstáculos, mírate en el espejo de ti mismo y serás libre y fuerte y dejarás de ser un títere de las
Más detallesUAA Sistemas Electrónicos Estructura de Datos Muñoz / Serna
2 Recursividad 2.1 Concepto de recursividad Se dice que una función es recursiva cuando dicha función se define en términos de la misma función. Es importante recordar que no todas la funciones pueden
Más detallesIntroducción Algoritmos de tipo dividir para vencer Algoritmos de rastreo Inverso. Recursividad. Programación Avanzada. 8 de septiembre de 2017
Recursividad Programación Avanzada 8 de septiembre de 2017 Contenido Introducción Objetivos Definición y características Caso de análisis: factorial Contenido Introducción Objetivos Definición y características
Más detallesTEMA 5: Subprogramas, programación modular
TEMA 5: Subprogramas, programación modular 5.1.-Definición de módulo. Programación modular La programación modular está basada en la técnica de diseño descendente, que como ya vimos consiste en dividir
Más detallesPráctica 5.- Recursividad
Benemérita Universidad Autónoma de Puebla Facultad de Ciencias de la Computación Programación Avanzada en Java Prim. 2009 Práctica 5.- Recursividad Datos de la práctica Fecha 6 de marzo de 2009 Conceptos
Más detallesESTRUCTURA DE DATOS: Tema 3. Recursividad
ESTRUCTURA DE DATOS: Tema 3. Recursividad Presenta: David Martínez Torres Universidad Tecnológica de la Mixteca Instituto de Computación Oficina No. 37 dtorres@mixteco.utm.mx Contenido 1. Directa e indirecta
Más detallesESTRUCTURA DE DATOS: Tema 3. Recursividad
ESTRUCTURA DE DATOS: Tema 3. Recursividad Presenta: David Martínez Torres Universidad Tecnológica de la Mixteca Instituto de Computación Oficina No. 37 dtorres@mixteco.utm.mx Contenido 1. Directa e indirecta
Más detallesTema 06: Recursividad
Tema 06: Recursividad M. en C. Edgardo Adrián Franco Martínez http://www.eafranco.com edfrancom@ipn.mx @edfrancom edgardoadrianfrancom (Prof. Edgardo A. Franco) 1 Contenido Recursión Recursividad Programación
Más detallesM.C. Yolanada Moyao Martínez
M.C. Yolanada Moyao Martínez Es una técnica de programación que permite que un bloque de instrucciones se ejecute n veces. En Java los métodos pueden llamarse a sí mismos. Si dentro de un método existe
Más detallesUNIVERSIDAD DON BOSCO FACULTAD DE ESTUDIOS TECNOLÓGICOS ESCUELA DE COMPUTACION
UNIVERSIDAD DON BOSCO FACULTAD DE ESTUDIOS TECNOLÓGICOS ESCUELA DE COMPUTACION CICLO: 01/ 2013 Nombre de la Practica: Lugar de Ejecución: Tiempo Estimado: MATERIA: GUIA DE LABORATORIO #11 Funciones recursivas
Más detallesComplejidad de algoritmos recursivos
Tema 3. Complejidad de algoritmos recursivos 1. INTRODUCCIÓN... 1 CLASIFICACIÓN DE FUNCIONES RECURSIVAS... 1 DISEÑO DE FUNCIONES RECURSIVAS... 2 2. VENTAJAS E INCONVENIENTES DE LA RECURSIVIDAD... 4 3.
Más detallesFundamentos de la programación
Fundamentos de la programación 10 Grado en Ingeniería Informática Grado en Ingeniería del Software Grado en Ingeniería de Computadores Facultad de Informática Universidad Complutense Concepto de recursión
Más detallesUnidad 2 Recursividad. 2.1 Definición 2.2 Procedimientos Recursivos 2.3 Ejemplos de Casos Recursivos
Unidad 2 Recursividad 2.1 Definición 2.2 Procedimientos Recursivos 2.3 Ejemplos de Casos Recursivos 2.1 Definición de Recursividad La Recursividad es una técnica de programación muy poderosa usada ampliamente
Más detallesPilas Motivación
Capítulo 4 Pilas Las pilas son estructuras muy sencillas y poderosas, también conocidas como LIFO (last in, first out) por la forma en que se trabaja con ellas. Ejemplo de ellas son las pilas de charolas
Más detallesTema: Programación Dinámica.
Programación IV. Guía No. 12 1 Facultad: Ingeniería Escuela: Computación Asignatura: Programación IV Tema: Programación Dinámica. Objetivos Específicos Definir el concepto de programación dinámica. Interpretar
Más detallesUnidad 2 Recursividad. 2.1 Definición 2.2 Procedimientos Recursivos 2.3 Ejemplos de Casos Recursivos
Unidad 2 Recursividad 2.1 Definición 2.2 Procedimientos Recursivos 2.3 Ejemplos de Casos Recursivos 2.1 Definición de Recursividad La Recursividad es una técnica de programación muy poderosa usada ampliamente
Más detallesRecursividad Definición
Recursividad Definición Un procedimiento o función se dice recursivo si durante su ejecución se invoca directa o indirectamente a sí mismo. Esta invocación depende al menos de una condición que actúa como
Más detallesAnálisis de algoritmos. Recursividad
Análisis de algoritmos Recursividad 1 Matrushka La Matrushka es una artesanía tradicional rusa. Es una muñeca de madera que contiene otra muñeca más pequeña dentro de sí. Ésta muñeca, también contiene
Más detallesLa recursividad forma parte del repertorio para resolver problemas en Computación y es de los métodos más poderosos y usados.
RECURSIVIDAD La recursividad forma parte del repertorio para resolver problemas en Computación y es de los métodos más poderosos y usados. Los algoritmos recursivos ofrecen soluciones estructuradas, modulares
Más detallesTema: Programación Dinámica.
Programación IV. Guía 11 1 Facultad: Ingeniería Escuela: Computación Asignatura: Programación IV Tema: Programación Dinámica. Objetivos Específicos Definir el concepto de programación dinámica. Interpretar
Más detallesEstructura de Datos. Recursividad. Primer Semestre, Indice
Estructura de Datos Recursividad Prof.: Mauricio Solar Prof.: Lorna Figueroa Primer Semestre, 2 Indice Introducción Definición Condiciones para la Recursividad Tipos de Recursividad Aplicaciones Ejemplo
Más detallesQué es la recursividad?
Recursividad 1 Ejemplo Matrushka La Matrushka es una artesanía tradicional rusa. Es una muñeca de madera que contiene otra muñeca más pequeña dentro de sí. Esta muñeca, también contiene otra muñeca dentro.
Más detallesRecursividad. Facultad de Ciencias de la Computación. Juan Carlos Conde R. Object-Oriented Programming I
Recursividad Facultad de Ciencias de la Computación Juan Carlos Conde R. Object-Oriented Programming I Contenido 1 Introducción 2 Escritura de Funciones 3 Tipos de Recursión 1 / 23 Contenido 1 Introducción
Más detallesFunciones Tipos de funciones y Recursividad
Funciones Tipos de funciones y Recursividad SESION 4 Definición Una función es una subrutina o subprograma que forman un programa que realiza tareas bien definidas. Todo programa en C consta de una o más
Más detallesConcepto de Recursión. Características de algoritmos recursivos. Ejemplos
RECURSION Temario Concepto de Recursión Características de algoritmos recursivos Ejemplos RECURSION Metodologías para resolver problemas: 1. Diseño Top Down 2. Recursión 3. Abstracción de Datos 4. Diseño
Más detallesProgramación 1 Tema 5. Instrucciones simples y estructuradas
Programación 1 Tema 5 Instrucciones simples y estructuradas Índice Instrucciones simples Instrucciones estructuradas 2 Instrucción ::= 3 Instrucciones.
Más detallesRecursión. Capítulo 4
Recursión Capítulo 4 Introducción La recursión o recursividad es un concepto amplio, con muchas variantes, y difícil de precisar con pocas palabras.. Actividades Cotidianas; fotografía donde se observa
Más detallesPROGRAMACION ESTRUCTURADA: Tema 3. Funciones
PROGRAMACION ESTRUCTURADA: Tema 3. Funciones Presenta: David Martínez Torres Universidad Tecnológica de la Mixteca Instituto de Computación Oficina No. 37 dtorres@mixteco.utm.mx Contenido 1. Definiciones
Más detallesFunciones: Pasos por Referencia Recursividad
Funciones: Pasos por Referencia Recursividad Fundamentos de Programación Fundamentos de Programación I Parámetros por referencia Con la instrucción return sólo se puede devolver un valor calculado. A veces
Más detallesCursosindustriales. Curso de C / C++ Por Deimos_hack
MÓDULO 1. ESTRUCTURAS Y FUNCIONES. En los capítulos anteriores has visto como los arrays permiten almacenar diferentes datos, pero todos del mismo tipo de dato. En la práctica esto no compensa debido a
Más detallesSemana Lenguajes 7de programación Tipos de lenguajes de programación
Semana Lenguajes 7de programación Semana 6 Empecemos! Estimados participantes, bienvenidos a esta nueva semana, en la que estudiaremos los lenguajes de programación más utilizados. No olvides repasar los
Más detallesProgramación I Recursividad.
Programación I Recursividad http://proguno.unsl.edu.ar proguno@unsl.edu.ar Recursividad Técnica de resolución de problemas particulares. La definición de un concepto es recursiva si el concepto es definido
Más detallesn! = 1 2 n 0! = 1 (n+1)! = (n + 1) n!
Capítulo 3 Recursión La recursión es un estilo autoreferencial de definición usado tanto en matemática como en informática. Es una herramienta de programación fundamental, particularmente importante para
Más detallesPILAS. Prof. Ing. M.Sc. Fulbia Torres
S ESTRUCTURAS DE DATOS 2006 Prof. UNIDAD II ESTRUCTURAS DE DATOS PILAS Definición. Operaciones. Implementación secuencial. Aplicaciones. Ejemplos. Ejercicios. DEFINICIÓN Una PILA (o stack) es una estructura
Más detallesCAPITULO 6: FUNCIONES
CAPITULO 6: FUNCIONES 1. INTRODUCCIÓN Un problema de programación en C se resuelve descomponiéndolo en varias partes. Cada una de estas partes se puede asociar a una función que resuelva su fracción correspondiente
Más detallesFunciones II. Fundamentos de Programación Fundamentos de Programación I
Funciones II Fundamentos de Programación Fundamentos de Programación I Ejercicio 1: Escribe una función que transforme un punto en coordenadas polares a cartesianas Entradas: Un punto como coordenadas
Más detallesTema: Funciones, Procedimientos y Recursividad en C#.
2 Programación I Programación I. Guía 6 3 Facultad: Ingeniería Escuela: Ingeniería en Computación Asignatura: Programación I Tema: Funciones, Procedimientos y Recursividad en C#. Objetivos Utilizar la
Más detallesINSTITUTO NACIONAL SUPERIOR DEL PROFESORADO TÉCNICO - TÉCNICO SUPERIOR EN INFORMÁTICA APLICADA - PROGRAMACIÓN I
RESOLUCIÓN DE PROBLEMAS Y ALGORITMOS La principal razón para que las personas aprendan lenguajes de programación es utilizar una computadora como una herramienta para la resolución de problemas. Cinco
Más detallesUNIDAD 7 Recursividad Concepto. Algoritmos recursivos. Seguimiento de la recursión. Algunos métodos recursivos de búsqueda y ordenación: M-Sort y
Recursividad Concepto. Algoritmos recursivos. Seguimiento de la recursión. Algunos métodos recursivos de búsqueda y ordenación: M-Sort y Q-Sort. Comparación de eficiencia en métodos Iterativos vs recursivos
Más detallesParadigmas de lenguajes de programación. Introducción a la programación imperativa. Lenguaje C. Programación imperativa
Paradigmas de lenguajes de programación Introducción a la programación imperativa Algoritmos y Estructuras de Datos I Paradigma: Definición del modo en el que se especifica el cómputo (que luego es implementado
Más detallesSentencias de Procesamiento Iterativo: while y do-while
ESTRUCTURAS CÍCLICAS Se discuten en este documento las sentencias que se utilizan en el lenguaje C++ para representar la tercera de las estructuras utilizadas en la programación estructurada: La Estructura
Más detallesPaso de parámetros. Universidad Europea de Madrid. Todos los derechos reservados.
Todos los derechos de propiedad intelectual de esta obra pertenecen en exclusiva a la Universidad Europea de Madrid, S.L.U. Queda terminantemente prohibida la reproducción, puesta a disposición del público
Más detallesProgramación 2. Lección 3. Introducción a la recursividad
Programación 2 Lección 3. Introducción a la recursividad 1 1. Definiciones recursivas Número natural y número entero Múltiplos de 7 Secuencia de datos Factorial de un número natural Sucesión de Fibonacci
Más detallesAPUNTADORES. Un apuntador es un objeto que apunta a otro objeto. Es decir, una variable cuyo valor es la dirección de memoria de otra variable.
APUNTADORES Un apuntador es un objeto que apunta a otro objeto. Es decir, una variable cuyo valor es la dirección de memoria de otra variable. No hay que confundir una dirección de memoria con el contenido
Más detallesRECURSIVIDAD. Prof. Ing. M.Sc. Fulbia Torres
ESTRUCTURAS DE DATOS 2006 Prof. UNIDAD II ESTRUCTURAS DE DATOS RECURSIVIDAD Definición. Estado base. Estado general. Ejemplos. Ejercicios. DEFINICIÓN Es una técnica de programación muy potente que permite
Más detallesEstructuración del programa en partes más pequeñas y sencillas
Introducción Estructuración del programa en partes más pequeñas y sencillas Modularización Propósito único Identificable Reusable Mayor claridad: programación, depuración, etc. Construcción de librerías
Más detallesINFORMATICA TECNICATURA DE NIVEL SUPERIOR ALGUNOS EJERCICIOS DE SELECCIÓN E ITERACION
INFORMATICA TECNICATURA DE NIVEL SUPERIOR ALGUNOS EJERCICIOS DE SELECCIÓN E ITERACION DIIAGRAMAS DE FLUJO Un diagrama de flujo es un dibujo que utiliza símbolos estándar de diagramación de algoritmos para
Más detallesIntroducción a c++ Introducción a la programación EIS Informática III
Introducción a c++ Un lenguaje de programación es un lenguaje formal diseñado para realizar procesos que pueden ser llevados a cabo por máquinas como las computadoras. Pueden usarse para crear programas
Más detallesCONTENIDO DE LA LECCIÓN 22
CONTENIDO DE LA LECCIÓN 22 UNIONES 1. Introducción 2 2. Almacenamiento de las Uniones en C++ 2 2.1. Ejemplo 22.1 3 3. Uniones anónimas en C++ 4 3.1. Ejemplo 22.2 4 4. Lo que necesita saber 5 22-1 LECCIÓN
Más detallesTECNICAS DE PROGRAMACION Universidad Católica Los Angeles de Chimbote RECURSIVIDAD Y SOBRECARGA DE METODOS
RECURSIVIDAD Y SOBRECARGA DE METODOS RECURSIVIDAD Un método es recursivo cuando se llama a si mismo ya sea directamente e indirectamente. Si un método recursivo se invoca con un caso base, simplemente
Más detallesTema: Funciones, Procedimientos y Recursividad en C#.
Tema: Funciones, Procedimientos y Recursividad en C#. Objetivos Programación I, Guía 6 1 Utilizar la sintaxis de las funciones definidas por el usuario (programador) para resolver problemas. Identificar
Más detallesTema: Funciones, Procedimientos y Recursividad en C#.
Tema: Funciones, Procedimientos y Recursividad en C#. Objetivos Programación I, Guía 7 1 Facultad: Ingeniería Escuela: Ingeniería en Computación Asignatura: Programación I Utilizar la sintaxis de las funciones
Más detallesDiseño y Análisis de Algoritmos
1. Recursividad 2. "Dividir para Reinar" 3. Recursividad y Tabulación (Programación Dinámica) 4. Métodos Matemáticos Funciones discretas Notación O Ecuaciones de recurrencia 5. Casos de Estudio Breve descripción
Más detallesRecursividad. 1.1 Concepto de Recursividad. Objetivos. Metodología de la Programación II Entender el concepto de recursividad.
Objetivos Metodología de la Programación II Entender el concepto de recursividad. Conocer los fundamentos del diseño de algoritmos recursivos. Recursividad Comprender la ejecución de algoritmos recursivos.
Más detallesTema: Funciones, Procedimientos y Recursividad en C#.
Programación I, Guía 6 1 Tema: Funciones, Procedimientos y Recursividad en C#. Objetivos Utilizar la sintaxis de las funciones definidas por el usuario (programador) para resolver problemas. Identificar
Más detallesSecuencias Calculadas
Secuencias Calculadas Estructuras de Iteración y Recursividad Prof. Hilda Contreras Programación 1 hildac.programacion1@gmail.com Secuencias Calculadas Se aplican a los problemas donde los elementos de
Más detallesAlgoritmos. Medios de expresión de un algoritmo. Diagrama de flujo
Algoritmos En general, no hay una definición formal de algoritmo. Muchos autores los señalan como listas de instrucciones para resolver un problema abstracto, es decir, que un número finito de pasos convierten
Más detalles1. Una pila funciona según el método LIFO (Last In First Out ). Se define la clase Pila de la siguiente forma:
Facultad de Ingeniería Establecimiento Público de Educación Superior, adscrito al Departamento de Antioquia Lógica de Programación II Taller Nº 3: Pilas, colas y recursividad Período 02 de 2014 Profesor:
Más detallesFundamentos de la POO 1
Fundamentos de la POO 1 La correcta aplicación de los conocimientos de clases y objetos nos permitirán llegar a los objetivos planteados y a generar programas que puedan ser fáciles de comprender para
Más detalles1. Los objetos conocidos, es decir, aquellos objetos de los cuales poseemos información total o parcial útil en la búsqueda de los objetos desconocido
3. METODOLOGÍA DE SOLUCIÓN DE PROBLEMAS CON EL COMPUTADOR El desarrollo de un programa que resuelva un problema dado es una tarea compleja, ya que es necesario tener en cuenta de manera simultánea muchos
Más detallesUna clasificación de los tipos de datos existentes en los diferentes lenguajes de programación se presenta a continuación:
Clase teórica 2 Algoritmos en C Página 1 de 6 TIPOS DE DATOS Una clasificación de los tipos de datos existentes en los diferentes lenguajes de programación se presenta a continuación: Por el momento nuestro
Más detallesTrabajo Práctico Nº 06
Tema: Recursividad 1. Dado el siguiente método: static int puzle (int base, int limite) if (base > limite) return -1; if (base = = limite) return base * puzle(base+1,limite); 1.1 Identificar: a) el caso(s)
Más detallesProcedimientos y funciones
Procedimientos y funciones 3 Contenido 3.1. Justificación 3.2. Declaración y llamada a procedimientos 3.2.1. La sentencia nula 3.3. Localidad, anidamiento, ámbito y visibilidad 3.4. Procedimientos con
Más detallesManual de referencia de C++ Parte IV Variables Punteros. Preparado por Prof. Luis A. Ortiz Ortiz
Manual de referencia de C++ Parte IV Variables Punteros Preparado por Prof. Luis A. Ortiz Ortiz TABLA DE CONTENIDO Memoria de la computadora... 1 Representación de la memoria de la computadora... 1 Declaración
Más detallesFundamentos de Programación. Resolución de Problemas y Diseño de Programas. Fundamentos de Programación. Página 0 de 27
Fundamentos de Programación. Resolución de Problemas y Diseño de Programas. Fundamentos de Programación. Página 0 de 27 Metodología general para la solución de un problema Comprensión del problema (entiende
Más detallesALGORITMICA Y PROGRAMACION POR OBJETOS I
ALGORITMICA Y PROGRAMACION POR OBJETOS I Nivel 1 Problemas, Soluciones y Programas Marcela Hernández Hoyos Solucionar un Problema = Construir un Programa Problema Programador Herramientas y Lenguajes Análisis
Más detallesProgramación 1. Tema II. Diseño de programas elementales. Lección 7. Diseño modular y descendente de programas
Programación 1 Tema II. Diseño de programas elementales Lección 7. Diseño modular y descendente de programas 1 Objetivos de la lección : En esta lección se aprende: a dotar a un programa C++ de una estructura
Más detallesTema 3. Estructuras de control
Tema 3. Estructuras de control 3.1. Secuencial 3.2. Selección 3.3. Repetición 2 Objetivos Objetivos del tema: Conocer y saber la utilidad de las tres estructuras de control (secuencial, alternativa y repetitiva)
Más detallesRecursividad... un análisis posterior. Jaime Gutiérrez Alfaro Introducción a la programación
Recursividad... un análisis posterior Jaime Gutiérrez Alfaro Introducción a la programación I semestre, 2015 Agenda Introducción Cálculos por aproximación Tipos de recursión Concepto de error Depuración
Más detallesProgramación Unidad 5. Recursividad. Programación TIG - TUP 1. Sede Regional Orán UNIVERSIDAD NACIONAL DE SALTA
Unidad 5 Recursividad 1 Recursión Se dice que un elemento es recursivo, cuando en la definición de ese elemento, utilizamos nuevamente a ese elemento. Por ejemplo, para definir la relación familiar de
Más detallesObjetivos. 1. Realizar exitosamente programas que involucren procesos que requieran iteraciones. Antecedentes
Objetivos a) El alumno conocerá las tres formas básicas existentes en C para realizar iteraciones y aprenderá a manejar las sentencias while, do-while y for. b) El alumno comprenderá la importancia que
Más detallesLaboratorio 5 Tema 7. Tipos de Datos Estructurados: Arreglos, Registros y Archivos
Laboratorio 5 Tema 7. Tipos de Datos Estructurados: Arreglos, Registros y Archivos PARTE 1. Arreglos Unidimensionales o Vectores Un arreglo es una estructura de datos conformada por una sucesión de celdas,
Más detallesEstructuras dinámicas lineales (i)
Estructuras dinámicas lineales (i) Introducción En la lección anterior se explicaron los conceptos de dinámicas y puntero; vimos la forma en que se implementan dichas tanto en la notación algorítmica como
Más detallesProgramación 1. Tema II. Diseño de los primeros programas. Lección 4. Diseño de algunos programas elementales
Programación 1 Tema II. Diseño de los primeros programas Lección 4. Diseño de algunos programas elementales 1 Objetivos de la lección: Aprender, paso a paso, una metodología de programación descendente
Más detallesInformática PRÀCTICA 2 Curs
Práctica Nº 2: Estructura general de un programa en C/C++. Introducción a las funciones de Entrada y salida en C++ (cin y cout) sin formato. Objetivos de la práctica: - Presentar la estructura general
Más detallesEste método de diseño de algoritmos en etapas, yendo de los conceptos generales a los de detalle, se conoce como método descendente (top-down).
PLANTEMAIENTO DEL PROBLEMA Identificación de entradas y salidas Un algoritmo puede ser definido como la secuencia ordenada de pasos, sin ambigüedades, que conducen a la resolución de un problema dado y
Más detallesTécnicas de prueba y corrección de algoritmos
Técnicas de prueba y corrección de algoritmos Diseño y Análisis de Algoritmos Cátedra de Programación Carrera de Ingeniería de Sistemas Prof. Isabel Besembel Carrera Algoritmos recursivos Aparente circularidad
Más detallesEjercicios sobre recursividad
Ejercicios sobre recursividad 11 de febrero de 2003 1. Implementa una función recursiva que devuelva la suma de los dígitos de un número natural, que se le pasa por parámetro. 2. Implementa una función
Más detallesU.A.B.C. Facultad de Ingeniería Programación Estructurada UNIDAD III
UNIDAD III Funciones 3.1 Forma general de una función. C fué diseñado como un lenguaje de programación estructurado, también llamado programación modular. Por esta razón, para escribir un programa se divide
Más detallesUNIVERSIDAD DON BOSCO FACULTAD DE ESTUDIOS TECNOLÓGICOS ESCUELA DE COMPUTACION
UNIVERSIDAD DON BOSCO FACULTAD DE ESTUDIOS TECNOLÓGICOS ESCUELA DE COMPUTACION CICLO: 01/ 2012 Nombre de la Practica: Lugar de Ejecución: Tiempo Estimado: MATERIA: GUIA DE LABORATORIO #10 Programación
Más detallesLenguaje C, tercer bloque: Funciones
Lenguaje C, tercer bloque: Funciones José Otero 1 Departamento de informática Universidad de Oviedo 28 de noviembre de 2007 Índice 1 Tipo puntero Concepto de puntero Operador dirección Operador indirección
Más detallesMetodología de la Programación II. Recursividad
Metodología de la Programación II Recursividad Objetivos Entender el concepto de recursividad. Conocer los fundamentos del diseño de algoritmos recursivos. Comprender la ejecución de algoritmos recursivos.
Más detallesUNIVERSIDAD AUTÓNOMA DEL ESTADO DE MÉXICO CENTRO UNIVERSITARIO UAEM ATLACOMULCO INGENIERÍA EN COMPUTACIÓN
UNIVERSIDAD AUTÓNOMA DEL ESTADO DE MÉXICO CENTRO UNIVERSITARIO UAEM ATLACOMULCO INGENIERÍA EN COMPUTACIÓN REPORTE DE INVESTIGACIÓN PROGRAMA FUNCIÓN FACTORIAL ALGORITMO PROGRAMA FUNCION FIBONACCI ALGORITMO
Más detallesTrabajo avanzado con consultas
1. ESTABLECER CRITERIOS H emos estado trabajando con consultas, incluso aplicando criterios más o menos complejos, pero sin pararnos mucho en cómo se construyen las expresiones que nos permiten recuperar
Más detallesFRACCION GENERATRIZ. Pasar de decimal exacto a fracción
FRACCION GENERATRIZ Un número decimal exacto o periódico puede expresarse en forma de fracción, llamada fracción generatriz, de las formas que indicamos: Pasar de decimal exacto a fracción Si la fracción
Más detallesPARTE II: ALGORÍTMICA
Programa de teoría Parte I. Estructuras de Datos.. Abstracciones y especificaciones.. Conjuntos y diccionarios.. Representación de conjuntos mediante árboles. 4. Grafos. Parte II. Algorítmica.. Análisis
Más detallesAlgoritmos y Estructuras de Datos Curso 06/07. Ejercicios
6.1.(Clase) Un programa que utiliza la técnica divide y vencerás, divide un problema de tamaño n en a subproblemas de tamaño n/b. El tiempo g(n) de la resolución directa (caso base) se considerará constante.
Más detallesTema 07: Backtraking. M. en C. Edgardo Adrián Franco Martínez edgardoadrianfrancom
Tema 07: Backtraking M. en C. Edgardo Adrián Franco Martínez http://www.eafranco.com edfrancom@ipn.mx @edfrancom edgardoadrianfrancom (Prof. Edgardo A. Franco) 1 Contenido Backtraking Búsqueda en profundidad
Más detallesProgramación Dinámica
Leopoldo Taravilse Facultad de Ciencias Exactas y Naturales Universidad de Buenos Aires Training Camp 2012 Leopoldo Taravilse (UBA) TC 2012 1 / 34 Contenidos 1 Recursión Principio de Optimalidad Ejemplos
Más detallesSUBPROGRAMAS. Los subprogramas pueden ser invocados varias veces desde diferentes partes del programa.
SUBPROGRAMAS Los subprogramas son un conjunto de instrucciones que realizan una labor específica y se comportan de manera independiente en un programa. Los subprogramas facilitan: Descomponer la complejidad
Más detallesCapítulo 4. Control de flujo. Continuar
Capítulo 4 Control de flujo Continuar Introducción El control de flujo permite encausar a la computadora sobre la ruta que debe seguir al momento de la ejecución de un programa, para ello se apoya en las
Más detallesAnálisis de algoritmos
Tema 09: Programación dinámica M. en C. Edgardo Adrián Franco Martínez http://www.eafranco.com edfrancom@ipn.mx @edfrancom edgardoadrianfrancom 1 Contenido Introducción Programación dinámica Enfoques de
Más detalles