karina.escalante11@gmail.com RECURSIVIDAD Como ya sabemos un subprograma puede llamar a cualquier otro subprograma y éste a otro, y así sucesivamente; es decir los subprogramas se pueden anidar. A llamar_a B; B llamar_a C; C llamar_a D Cuando se produce el retorno tendremos: D retornar_a C; C retornar_a B; B retornar_a A;
¿Qué sucede si dos subprogramas de una secuencia son los
mismos? A llamar_a A RECURSIVIDAD La Recursividad es aquella propiedad que posee una función por la cual dicha función puede llamarse a sí misma.
La recursión es una herramienta muy potente en algunas
aplicaciones, sobre todo de cálculo. Se puede utilizar la recursividad como una alternativa a la iteración (repetición).
La razón que existen lenguajes que admiten la recursividad
se debe a la existencia de estructuras específicas tipo pilas para este tipo de procesos y memorias dinámicas. Las direcciones de retorno y el estado de cada subprograma se guardan en este tipo de estructuras. PROPIEDADES DE LA RECURSIVIDAD Todo proceso recursivo tiene dos partes:
1. Una caso base o caso trivial que se resuelve sin
recursión. 2. Un caso general que se acerca o reduce al caso base. DISEÑO DE UN ALGORITMO RECURSIVO Para diseñar algoritmos recursivos debe seguir los pasos siguientes:
1. Dividir el problema en dos partes.
2. Hallar el caso base o caso trivial que se resuelve sin recursión. 3. Establecer la regla general o caso general, el cual debe acercarse al caso base utilizando la estructura condicional. 4. Verificar que la recursión siempre termine. Ejemplo: Si se ejecuta este algoritmo, para n=3 se obtienen los Algoritmo: Factorial siguientes valores: Variables: 1º paso: entero: n, n3 Inicio // programa principal factorial 3*factorial(2) (guarda el valor de n=3) leer (n) 2º paso: factorialn*factorial(n-1) n2 Escribir (factorial) factorial 2*factorial(1) (guarda el valor de n=2) Fin 3º paso: n1 Entero funcion factorial(E entero: n) factorial 1*factorial(0) (guarda el valor de n=1) Inicio 4º paso: si n==0 entonces n0 devolver(1) devolver(1) si_no 3º paso: devolver(n*factorial(n-1)) Recupera n=1 de la pila fin_si devolver(1*1) Fin_funcion 2º paso: Recupera n=2 de la pila devolver(2*1) 1º paso: Recupera n=3 de la pila devolver(3*2) RECURSIVIDAD DIRECTA E INDIRECTA Si una función, procedimiento o método se invoca a sí misma, el proceso se denomina recursión directa pero si una función, procedimiento o método puede invocarse a una segunda función, procedimiento o método que a su vez invoca a la primera, este proceso se conoce como recursión indirecta o mutua.
Un requisito para que un algoritmo recursivo sea correcto es que no genere
una secuencia infinita de llamadas sobre sí mismo. Para evitar lo anterior, el programa recursivo debe incluir un componente base (condición de salida) en el que la f(n) se defina directamente (es decir no recursivamente) para uno o más valores del parámetro. RECURSIVIDAD DIRECTA Ejemplo: Si se ejecuta este algoritmo, para n=3 se obtienen los Algoritmo: Factorial siguientes valores: Variables: 1º paso: entero: n, n3 Inicio // programa principal factorial 3*factorial(2) (guarda el valor de n=3) leer (n) 2º paso: factorialn*factorial(n-1) n2 Escribir (factorial) factorial 2*factorial(1) (guarda el valor de n=2) Fin 3º paso: n1 Entero funcion factorial(E entero: n) factorial 1*factorial(0) (guarda el valor de n=1) Inicio 4º paso: si n==0 entonces n0 devolver(1) devolver(1) si_no 3º paso: devolver(n*factorial(n-1)) Recupera n=1 de la pila fin_si devolver(1*1) Fin_funcion 2º paso: Recupera n=2 de la pila devolver(2*1) 1º paso: Recupera n=3 de la pila devolver(3*2) RECURSIVIDAD INDIRECTA Ejemplo: Algoritmo: Par o Impar Entero funcion espar(E entero: n) Variables: Inicio entero: n,m si n==0 entonces Inicio // programa principal devolver(1) leer (n) si_no mespar(n) devolver(esimpar(n-1)) si m==1 entonces fin_si Escribir (m es Par) Fin_funcion si_no Escribir(m es impar) Entero funcion esimpar(E entero: n) fin_si Inicio Fin si n==0 entonces devolver(0) si_no devolver(espar(n-1)) fin_si Fin_funcion Ejemplo: Si se ejecuta este algoritmo, para n=3 se obtienen los siguientes valores: 1º paso: n3 espar(3) devuelve(esimpar(3-1)) 2º paso: n2 esimpar(2) devuelve(espar(2-1)) 3º paso: n1 espar(1) devuelve(esimpar(0)) 4º paso: esimpar(0) devuelve(0) 3º paso: devuelve(0) 2º paso: devuelve(0) 1º paso: devuelve(0) RECURSIVIDAD VS ITERACIÓN Tanto la iteración como la recursión se basan en una estructura de control: la iteración utiliza una estructura repetitiva y la recursión utiliza una estructura de selección.
La iteración utiliza explícitamente una estructura repetitiva mientras que la
recursión consigue la repetición mediante llamadas repetidas.
La iteración termina cuando la condición del bucle no se cumple mientras
que la recursión termina cuando se reconoce un caso base o la condición de salida se alcanza. Ejemplo: Método Iterativo Método Recursivo Algoritmo: Factorial Algoritmo: Factorial Variables: Variables: entero: i,n,m entero: n Inicio Inicio // programa principal i 1 leer (n) m1 factorialn*factorial(n-1) leer (n) Escribir (factorial) mientras i<=n entonces Fin m m*i i i+1 Entero funcion factorial(E entero: n) fin_mientras Inicio escribir(m) si n==0 entonces Fin devolver(1) si_no devolver(n*factorial(n-1)) fin_si Fin_funcion RECURSIVIDAD INFINITA La recursión infinita significa que cada llamada recursiva produce otra llamada recursiva y ésta a su vez otra llamada recursiva y así para siempre.
El flujo de control de un algoritmo recursivo requiere tres condiciones
para una terminación normal: • Un test para detener (o continuar) la recursión, llamada condición de salida o caso base. • Una llamada recursiva (para continuar la recursión). • Un caso final para terminar la recursión. Ejemplo: Algoritmo: Suma Si se ejecuta este algoritmo, para n=3 se Variables: obtiene: entero: n Inicio // programa principal 1º paso: leer (n) n3 msum(n) m 3+sum(2) (guarda el valor de n=3) Escribir (m) 2º paso: Fin n2 m 2+sum(1) (guarda el valor de n=2) Entero funcion sum(E entero: n) 3º paso: n1 Inicio devuelve (1) //test para parar o continuar 2º paso: (condición de salida) Recupera n=2 de la pila si n==1 entonces devolver(2+1) devolver(1) //se detiene 1º paso: si_no //caso recursivo Recupera n=3 de la pila devolver(n+sum(n-1)) devolver(3+3) fin_si Fin_funcion RESOLUCIÓN DE PROBLEMAS COMPLEJOS CON RECURSIVIDAD Muchos problemas de computadora tienen una formulación simple y elegante que se traduce directamente a código recursivo. Ahora vamos a describir el famoso problema “Las Torres de Hanoi” LAS TORRES DE HANOI Para mover n discos de A(VarIni) a C(VarFin) usando B(VarCentral) como auxiliar: void Si n == 1 hacer mover el disco 1 de A a C. Si_no mover (n-1) discos desde A a B utilizando C mover el disco n desde A a C mover (n-1) discos desde B a C utilizando A Fin_si LAS TORRES DE HANOI int hanoi(E:int n, char varini, char varfin, char varcentral) Inicio si n == 1 hacer escribir( "mover disco 1 de “, varini, " a “, varfin ) si_no hanoi(n-1, varini, varcentral, varfin); escribir("mover disco “,n," de “,varini," a “, varfin) hanoi (n-1, varcentral, varfin, varini); fin_si Fin_funcion Ejemplo para 3 Discos: Ejercicios 1. Realizar el código de manera iterativa y recursiva los siguientes ejercicios: Sucesión de Fibonacci. La multiplicación de dos números naturales. La potencia de un número natural elevado a un entero no negativo. El máximo común divisor de dos número enteros. La representación binaria de un número entero no negativo. Muestre de manera descendente los enteros desde n hasta 1. Que reciba un entero n y lo devuelva en sentido inverso. Ejemplo: 1234, la función debe devolver 4321 Ejercicios 2. La definición habitual de los coeficientes binomiales se expresa en términos de factoriales:
(0≤ 𝑘 ≤n)
Sin embargo, también es posible dar una definición recursiva:
Utilice esta definición recursiva para escribir, la función
binomial(n,k). Pruebe para k=3 y n=3. Ejercicios 3. En teoría de la computación, la función de Ackermann es una función recursiva que toma dos números naturales como argumentos y devuelve un único número natural.
Escribir la función recursiva que implemente esta función.
Ejercicios 4. Escribir una función recursiva que calcule la raíz cuadrada de un número no negativo. Los argumentos de la función son 3 números N, A y E. Donde: • N: Es el número al que se le calculará la raíz cuadrada. • A: Es una aproximación de la raíz cuadrada. • E: Error aceptado en el cálculo. Utilice la siguiente definición recursiva: Ejercicios 5. Los números de Catalán forman una secuencia de números naturales. El n-ésimo número de Catalán se puede calcular de forma recursiva: Ejercicios de Funciones 1. Realizar el código de los siguientes ejercicios, utilizando funciones: Verificar que una fecha es correcta. Ejemplo: 28/10/2015. Encuentre los divisores comunes de dos números. Muestre los primeros m múltiplos de n. Realizar una función llamada media2. Debe ingresar dos números reales, y el programa les devuelve un número real que es la media de los dos números ingresados. Encuentre si un número es positivo o negativo.