Estructurade Datos(s0e730ea9ff0859b2.jimcontent.com/download/version/... · 2014. 9. 5. ·...
Transcript of Estructurade Datos(s0e730ea9ff0859b2.jimcontent.com/download/version/... · 2014. 9. 5. ·...
Estructura de Datos
RECURSIVIDAD La recursividad es aquella propiedad que posee una función por la cual dicha función puede . La recursión es una herramienta poderosa e importante en resolución de problemas y en programación. Se puede utilizar la recursividad como una alternativa a la iteración.
Estructura de Datos
Algoritmos recursivos
Una función que tiene sentencias entre las que se encuentra al menos una que llama a la propia función se dice que es recursiva. En el diseño de un algoritmo recursivo hay que tener en cuenta que: • El instrumento necesario para expresar los programas recursivamente es la
función • Una función tiene recursividad directa cuando se llama a si misma dentro de
su propia definición • Una función tiene recursividad indirecta si llama a otra función que, a su vez,
contiene una referencia directa o indirecta a la primera
Estructura de Datos
Algoritmos recursivos Continuación… • El cuerpo de una función recursiva debe tener una o varias instrucciones
selectivas donde establece para los casos generales las soluciones generales, y para los casos triviales las soluciones triviales
• Cada llamada recursiva debe disminuir el tamaño del ejemplar de entrada de tal manera que se acerque a la solución trivial
• Cada vez que se llame a una función recursiva todos los valores de los parámetros formales y variables locales son almacenados en una pila
• Cuando termine de ejecutarse la función recursiva retorna al nivel inmediatamente anterior. En la pila se recuperan los valores tanto de los parámetros como de las variables locales, y se continua con la ejecución de la siguiente instrucción a la llamada recursiva.
Estructura de Datos
Procedimientos recursivos Los procedimientos recursivos o recurrentes se pueden clasificar en dos formas distintas: - Recursividad directa o - Recursividad indirecta La recursividad directa se presenta cuando el método se manda llamar a sí mismo dentro de su propio cuerpo de instrucciones. public int Metodo(int n) { : n = Metodo(n-1);
}
Estructura de Datos
La recursividad indirecta se manifiesta cundo un método llama a otro y dentro del segundo se manda llamar al primero. O cuando existe la llamada a métodos de forma encadenada y al terminar el último método llamado, transfiere el control al anterior, hasta llegar al método que inicio la serie de llamadas. public int Metodo1(int n) { : n = Metodo2(n-1); } public int Metodo2(int n) { : n = Metodo1(n-1); }
Estructura de Datos
Ejemplo: El siguiente programa permite observar el funcionamiento de la recursividad y como los valores de los parámetros son recuperados de la pila a la salida de la recursividad. La función contar decrementa el parámetro y lo muestra y si el valor es mayor que cero, se llama a si misma donde decrementa el parámetro una vez mas, etc. Cuando el parámetro alcanza el valor de cero, la función ya no se llama a si misma y se producen sucesivos retornos al punto siguiente a donde se efectuaron las llamadas, donde se recupera de la pila el valor del parámetro y se muestra.
Estructura de Datos
Métodos para la resolución de problemas que usan recursividad Entre las distintas técnicas para diseñar algoritmos recursivos destacan la estrategia de Divide y Vencerás y la de Retroceso o Backtracking Divide y Vence El diseño de algoritmos basados en esta técnica consiste en transformar (dividir) un problema de tamaño n en problemas mas pequeños, de tamaño menos que n pero similares al problema original. De modo que resolviendo los subproblemas y combinando las soluciones se puede construir fácilmente una solución del problema completo (venceras).
Estructura de Datos
Un algoritmo “divide y vence” puede ser definido de manera recursiva, de tal modo que se llama a si mismo sobre un conjunto menor de elementos. La condición para dejar de hacer llamadas es, normalmente, la obtención de un solo elemento (o muy pocos elementos) lo que se denomina el caso base o caso trivial. El algoritmo general del método es el siguiente: Algoritmo DivideyVence (E <limites del problema a tratar>; …) Inicio
Si <caso trivial> entonces <solución trivial> si_no <dividir el problema en subproblemas> desde <cada subproblema i> hacer DivideyVence(<subproblema i>,…) fin desde <combinar las soluciones de los subproblemas> fin si
fin algoritmo
Estructura de Datos Backtracking (Retroceso) Es un método de resolución de problemas basado en el tanteo sistemático (prueba y error) y en el que la solución del problema se divide en pasos. La solución del paso i-esimo se resuelve en función del paso i-esimo + 1. Las técnicas de Backtracking se pueden emplear con la finalidad de encontrar una solución, todas las soluciones o la solución optima al problema planteado. Procedimiento Ensayar (E entero: i; E/S lógico: éxito; …) Inicio
<inicializa las posibilidades> mientras <queden posibilidades> y no éxito hacer <toma la siguiente posibilidad> si <la posibilidad es aceptable> entonces <anota la posibilidad como parte de la solución> si <se encontró una solución general> entonces éxito ß verdad sino Ensayar (i+1, éxito, …) Fin si Si no éxito entonces <desanota la posibilidad como parte de la solución> fin si fin si fin mientras
fin procedimiento
Estructura de Datos
Forma de generar la recursividad Un problema clásico: El factorial de un número. Todos conocemos que la definición matemática del factorial de un número n se obtiene de la siguiente forma: n! = 1*2*3*.......*n ó n! = n*(n-1)*(n-2)*.....1 Por definición matemática, también sabemos que: 0! = 1 Con lo que tendríamos la siguiente definición de factorial: n!=1 Si n=0 Caso Base n*(n-1) Otros casos Parte Recursiva
Estructura de Datos
Un problema que puede resolverse de manera recursiva, debe tener por lo menos caso base y 1 parte recursiva, sino no hay recursión. Ahora, para implementarlo en un lenguaje de programación como Java, solo tenemos que traducir nuestros casos bases y partes recursivas:
Funcionamiento del proceso n Llamado a factorial 4 4*factorial(3) 3 3*factorial(2) 2 2*factorial(1) 1 1*factorial(0) 0 1 En general el proceso es (4*factorial(3*factorial(2*factorial(1*factorial(0)))))
Estructura de Datos
Realizar de manera recursiva la sumatoria de n números naturales de manera recursiva. La sumatoria de n números se realiza de la siguiente forma: n=10 1+2+3+4+5+6+7+8+9+10 = 10+9+8+7+6+5+4+3+2+1
Estructura de Datos
public class SumaRecursiva { public static int total; public static int suma (int valor){ if (valor > 0) { total = valor + suma(valor-1); } //System.out.println(total); return total; } public static void main(String[] args) { int valor = 10; System.out.println(suma(valor)); } }
Estructura de Datos
Realizar de manera recursiva la potencia de un número para n. El cálculo de la potencia de un número se resuelve de la siguiente manera. Xp=X*X(p-1)*X(p-2)*X(p-3)……= 25= 2 * 2 * 2 * 2 * 2 Sabemos que 20= 1 por lo que determinamos 1 si p = 0 paso básico n * (n, p-1) si p > 0 paso inductivo 24 2*potencia(2*potencia(2*potencia(2*potencia(2,0)) Potencia(2,4)=2*potencia(2,3)=16 Potencia(2,3)=2*potencia(2,2)=8 Potencia(2,2)=2*potencia(2,1)=4 Potencia(2,1)=2*potencia(2,0)=2 Potencia(2,0)=1
Estructura de Datos
escriba una función recursiva que calcule los numero de Fibonacci Definición recursiva de la función: Fibonacci (n) = Fibonacci (n-1) + Fibonacci (n-2) si n > 1 y Fibonacci(n) = n en otro caso
Estructura de Datos
Escriba un programa que mediante recursividad indirecta decida si un numero es par o impar Definición recursiva de la función: Par (n) = Impar (n-1) si n > 1 Impar (n) = Par (n-1) si n > 1 Par (0) = True Impar (0) = False