1. INTRODUCCIÓN
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 y
elegantemente simples.
La recursividad es un concepto fundamental en matemáticas y en computación.
Una definición recursiva dice cómo obtener conceptos nuevos empleando el
mismo concepto que intenta describir.
En toda situación en la cual la respuesta pueda ser expresada como una
secuencia de movimientos, pasos o transformaciones gobernadas por un conjunto
de reglas no ambiguas, la fórmula recursiva es un buen candidato para resolver el
problema.
• Ámbito de Aplicación:
– General
– Problemas cuya solución se puede hallar solucionando el mismo problema
pero con un caso de menor tamaño.
• Razones de uso:
– Problemas “casi” irresolubles con las estructuras iterativas.
– Soluciones elegantes.
– Soluciones más simples.
• Condición necesaria:
ASIGNACIÓN DINÁMICA DE MEMORIA
Recursividad
La recursividad consiste en realizar una definición de un concepto en términos del
propio concepto que se está definiendo.
¿En qué consiste la recursividad?
– En el cuerpo de sentencias del subalgoritmo se invoca al propio
subalgoritmo para resolver “una versión más pequeña” del problema
Original.
– Habrá un caso (o varios) tan simple que pueda resolverse directamente sin
necesidad de hacer otra llamada recursiva
Ejemplos:
·Los números naturales se pueden definir de la siguiente forma:
2. 0 es un Número natural y el sucesor de un número natural
es también un número natural.
·El factorial de un número natural n, es 1 si dicho número es 0, o n multiplicado por
el factorial del número n-1, en caso contrario.
·La n-ésima potencia de un número x, es 1 si n es igual a 0, o el producto de x por
la potencia (n-1)-ésima de x, cuando n es
mayor que 0.
Ejemplo: Factorial de un natural.
1 si n == 0
Factorial(n)= n*Factorial(n-1) si n > 0
• Ejemplo: Factorial de un natural.
ALGORITMO N Factorial(E n:N)
VAR
N fact
INICIO
SI n == 0 ENTONCES fact = 1
SINO fact = n*Factorial(n-1)
FINSI
DEVOLVER fact
FIN
Escritura de programas recursivos
• 1.-Obtención de una definición exacta del problema
• 2.-Determinar el tamaño del problema completo que hay que resolver
Parámetros en la llamada inicial
• 3.-Resolver el(los) casos bases o triviales (no recursivos).
• 4.-Resolver el caso general en términos de un caso más
pequeño (llamada recursiva).
Distintos parámetros
3. Ejemplos
• Combinaciones:¿cuántas combinaciones de cierto tamaño pueden hacerse de un
grupo total de elementos?
– C: número total de combinaciones
– Grupo: tamaño total del grupo del que elegir
– Miembros: tamaño de cada subgrupo
– Grupo>=Miembros
-Grupo si Miembros=1
C(Grupo, Miembros) -1 si Miembros=Grupo
-C(Grupo-1,Miembros-1)+C(Grupo-1,Miembros) si Grupo>Miembros>1
Características de los problemas que pueden ser resueltos de manera recursiva:
-.Los problemas pueden ser redefinidos en términos de uno o
más subproblemas, idénticos en naturaleza al problema original, pero de alguna
forma menores en tamaño.
-.Uno o más subproblemas tienen solución directa o conocida, no recursiva.
-Aplicando la redefinición del problema en términos de problemas más pequeños,
dicho problema se reduce sucesivamente a los subproblemas cuyas soluciones se
conocen directamente.
-La solución a los problemas más simples se utiliza para construir la solución al
problema inicial.
Ejemplos simples de recursividad.
A) Cálculo del factorial de un número, por ejemplo, 5.
5! = 5 * 4!
4! = 4 * 3! DESCOMPOSICIÓN DEL PROBLEMA
3!= 3 * 2!
2! = 2 * 1!
1! = 1 * 0!
SOLUCIÓN CONOCIDA O DIRECTA 0! = 1
1! = 1 * 0! = 1
2! = 2 * 1! = 2
3! = 3 * 2! = 6 RESOLUCIÓN DE PROBLEMAS MÁS COMPLEJOS A PARTIR DE
OTROS MÁS SIMPLES
4! = 4 * 3! = 24
5! = 5 * 4! = 120
4. Diseño de módulos recursivos.
·Módulo M con una llamada a sí mismo: módulo recursivo directo.
·Módulo M con una llamada a otro F, que hace una llamada a
M: Módulo recursivo indirecto.
Ejemplo: Implementación del factorial de un número.
public long factorial (long n)
{
if (n == 0) return 1;
else return n * factorial(n-1);
}
Ejemplo: la sucesión de Fibonacci.
1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ...
·El tercer término de la sucesión se obtiene sumando el segundo
y el primero. El cuarto, a partir de la suma del tercero y el
segundo.
·El problema: calcular el valor del n-ésimo término de la
solución, que se obtendrá sumando los términos n-1 y n-2.
Las respuestas a la preguntas anteriores serían:
·[P1] fibonacci(n) = fibonacci(n-1) + fibonacci(n-2).
·[P2] Casos bases: fibonacci(1) = 1 y fibonacci(2)=1.
·[P3] En cada llamada a la rutina fibonacci se reduce el tamaño
del problema en uno o en dos, por lo que siempre se alcanzará
uno de los dos casos bases.
·[P4] fibonacci(3) = fibonacci(2) + fibonacci(1) = 1 + 1.
Se construye la solución del problema n==2 a partir de los dos casos bases.
Paso de parámetros a los módulos recursivos.
Utilización de parámetros formales: cuidado al decidir si
los parámetros serán de entrada, salida o entrada/salida.
Veamos un ejemplo:
public long factorial (long n)
{
if (n == 0) return 1;
else
{
n = n -1;
return (n+1) * factorial(n);
}
5. ¿Qué ocurre cuando se empiezan a devolver las llamadas recursivas?
n siempre será igual a 0, y se devolverá siempre 1
_
El factorial de cualquier número será 0 (INCORRECTO)
¿Recursión o iteración?
• Ventajas de la Recursión ya conocidas
– Soluciones simples, claras.
– Soluciones elegantes.
– Soluciones a problemas complejos.
• Desventajas de la Recursión: INEFICIENCIA
– Sobrecarga asociada con las llamadas a subalgoritmos
• Una simple llamada puede generar un gran numero de llamadas recursivas.
(Fact(n) genera n llamadas recursivas)
• ¿La claridad compensa la sobrecarga?
• El valor de la recursividad reside en el hecho de que se puede usar para resolver
problemas sin fácil solución iterativa.
– La ineficiencia inherente de algunos algoritmos recursivos.