1. Introducción al trabajo. El siguiente trabajo trata del análisis, de la programación dinámica. Siendo esta una solución de mejora a la poca eficiencia de la programación recursiva. La manera de afrontar este trabajo, y explicar en un modo sencillo, que entienda todo el mundo, tras consultar muchas fuentes, es el siguiente, primero veremos a grandes rasgos, en que consiste la programación recursiva, sus propiedades, definiciones, ventajas e inconvenientes, y todo ello acompañado de ejemplos, y uno en común junto a la programación dinámica, de manera que podamos observar el mismo problema desde las dos perspectivas, que es, el calculo de los números de Fibonacci. El por que de hablar extendidamente de la programación recursiva es, porque esta, junto con algunas técnicas de programación como “el divide y vencerás, algoritmo voraz, o backtracking”, la programación dinámica no es mas que una mejora bastante significativa basada en la programación recursiva, aprovechando los cálculos que generan las llamadas, e ir almacenándolos para su posterior uso, no teniendo que volver a calcularlo, aunque lo veremos con mas extensión mas adelante. 2. Recursividad 2.i. Introducción a la Recursividad. El área de la programación es muy amplia y con muchos detalles. Los programadores necesitan ser capaces de resolver todos los problemas que se les presente a través del computador aun cuando en el lenguaje que utilizan no haya una manera directa de resolver los problemas. En los lenguajes de programación, se puede aplicar una técnica que se le dio el nombre de recursividad por su funcionalidad. Esta técnica es utilizada en la programación estructurada para resolver problemas que tengan que ver con el factorial de un número, o juegos de lógica. Las asignaciones de memoria pueden ser dinámicas o estáticas y hay diferencias entre estas dos y se pueden aplicar las dos en un programa cualquiera. 2.ii Conceptos de Recursividad. La recursividad es una técnica de programación importante. Se utiliza para realizar una llamada a una función desde la misma función. Como ejemplo útil se puede presentar el cálculo de números factoriales. Él factorial de 0 es, por definición, 1. Los factoriales de números mayores se calculan mediante la multiplicación de 1 * 2 * …, incrementando el número de 1 en 1 hasta llegar al número para el que se está calculando el factorial. El siguiente párrafo muestra una función, expresada con palabras, que calcula un factorial. “Si el número es menor que cero, se rechaza. Si no es un entero, se redondea al siguiente entero. Si el número es cero, su factorial es uno. Si el número es mayor que cero, se multiplica por él factorial del número me nor inmediato.” Para calcular el factorial de cualquier número mayor que cero hay que calcular como mínimo el factorial de otro número. La función que se utiliza es la función en la que se encuentra en estos momentos, esta función debe llamarse a sí misma para el número menor inmediato, para poder ejecutarse en el número actual. Esto es un ejemplo de recursividad. La recursividad y la iteración (ejecución en bucle) están muy relacionadas, cualquier acción que pueda realizarse con la recursividad puede realizarse con iteración y viceversa. Normalmente, un cálculo determinado se prestará a una técnica u otra, sólo necesita elegir el enfoque más natural o con el que se sienta más cómodo. Claramente, esta técnica puede constituir un modo de meterse en problemas. Es fácil crear una función recursiva que no llegue a devolver nunca un resultado definitivo y no pueda llegar a un punto de finalización. Este tipo de recursividad hace que el sistema ejecute lo que se conoce como bucle “infinito”. Ejemplo: Secuencia de números de Fibonacci. Para entender mejor lo que en realidad es el concepto de recursión veremos un poco lo referente a la secuencia de Fibonacci. Principalmente habría que aclarar que es un ejemplo menos familiar que el del factorial, que consiste en la secuencia de enteros. 0,1,1,2,3,5,8,13,21,34,…, Cada elemento en esta secuencia es la suma de los precedentes (por ejemplo 0 + 1 = 0, 1 + 1 = 2, 1 + 2 = 3, 2 + 3 = 5, …) sean fib(0) = 0, fib (1) = 1 y así sucesivamente, entonces puede definirse la secuencia de Fibonacci mediante la definición recursiva (define un objeto en términos de un caso mas simple de si mismo): fib (n) = n if n = = 0 or n = = 1 fib (n) = fib (n - 2) + fib (n - 1) if n >= 2 Por ejemplo, para calcular fib (6), puede aplicarse la definición de manera recursiva para obtener: Fib (6) = fib (4) + fib (5) = fib (2) + fib (3) + fib (5) = fib (0) + fib (1) + fib (3) + fib (5) = 0 + 1 fib (3) + fib (5) 1. + fib (1) + fib (2) + fib(5) = 1. + 1 + fib(0) + fib (1) + fib (5) = 2. + 0 + 1 + fib(5) = 3 + fib (3) + fib (4) = 3. + fib (1) + fib (2) + fib (4) = 3 + 1 + fib (0) + fib (1) + fib (4) = 4. + 0 + 1 + fib (2) + fib (3) = 5 + fib (0) + fib (1) + fib (3) = 5. + 0 + 1 + fib (1) + fib (2) = 6 + 1 + fib (0) + fib (1) = 6. + 0 + 1 = 8 Obsérvese que la definición recursiva de los números de Fibonacci difiere de las definiciones recursivas de la función factorial y de la multiplicación . La definición recursiva de fib se refiere dos veces a sí misma . Por ejemplo, fib (6) = fib (4) + fib (5), de tal manera que al calcular fib (6), fib tiene que aplicarse de manera recursiva dos veces. Sin embargo calcular fib (5) también implica calcular fib (4), así que al aplicar la definición hay mucha redundancia de cálculo. En ejemplo anterior, fib(3) se calcula tres veces por separado. Sería mucho más eficiente “recordar” el valor de fib(3) la primera vez que se calcula y volver a usarlo cada vez que se necesite. Es mucho mas eficiente un método iterativo como el que sigue parar calcular fib (n). If (n < = 1) return (n); lofib = 0 ; hifib = 1 ; for (i = 2; i < = n; i ++) { x = lofib ; lofib = hifib ; hifib = x + lofib ; } /* fin del for*/ return (hifib) ; Compárese el numero de adiciones (sin incluir los incrementos de la variable índice, i) que se ejecutan para calcular fib (6) mediante este algoritmo al usar la definición recursiva. En el caso de la función factorial, tienen que ejecutarse el mismo número de multiplicaciones para calcular n! Mediante ambos métodos: recursivo e iterativo. Lo mismo ocurre con el número de sumas en los dos métodos al calcular la multiplicación. Sin embargo, en el caso de los números de Fibonacci, el método recursivo es mucho más costoso que el iterativo.


Búsqueda personalizada

GFDL