Post on 26-Apr-2018
Recursión
Introducción a la Computación
Clase 15
Patricia Borensztejn
El concepto de la recursión
• Recursión, recurrencia o recursividad es la forma en la cual se especifica un proceso basado en su propia definición.
Mas imágenes recursivas
• Triángulo de Sierpinsky (1915)
Triángulo de Sierpinsky
• Construcción:
1. Comenzamos con un triángulo.
2. Lo reducimos a la mitad de la altura y la mitad del lado y lo triplicamos, haciendo que cada uno toque a los otros dos en un extremo
3. Volvemos al paso 2 por cada triángulo generado.
Recursión
• Definición de la sintaxis de un lenguaje de programación (LISP):
– expresión ::= átomo | lista
– átomo ::= número | símbolo
– número ::= [+-]?['0'-'9']+
– símbolo ::= ['A'-'Z'<nowiki>'</nowiki>a'-'z'].*
– lista ::= '(' expresión* ')'
Recursión: factorial
• Definición de una función matemática de forma recursiva:
Recursión en los lenguajes de programación
• Una función que se llama a si misma directa o indirectamente, es una función recursiva.
Factorial recursivo
factorial(5)
*
5 factorial(4)
*
4 factorial(3)
*
3 factorial(2)
*
2 factorial(1)
Camino de Ida: se contruye por cada activación de la función su bloque de activación en la pila
Camino de Ida
Factorial recursivo
factorial(5)
*
5 factorial(4)
*
4 factorial(3)
*
3 factorial(2)
*
2
Camino de vuelta
factorial(1) devuelve 1 Y se libera su bloque de activación
1
Factorial recursivo
factorial(5)
*
5 factorial(4)
*
4 factorial(3)
*
3
Camino de vuelta
factorial(2) devuelve 2 Y se libera su bloque de activación
2
Factorial recursivo
factorial(5)
*
5 factorial(4)
*
4 6
Camino de vuelta
factorial(3) devuelve 6 Y se libera su bloque de activación
Factorial recursivo
factorial(5)
*
5 24
Camino de vuelta
factorial(4) devuelve 24 Y se libera su bloque de activación
Factorial recursivo
factorial(5) devuelve 120 Y se libera su bloque de activación
Factorial recursivo, versión en C
• Mostramos también el estado de la pila con los bloques de activación …. en que momento? O sea, que estamos viendo en la pantalla?
Recursión indirecta y declaración anticipada en C
• El problema es que par llama a impar, con lo cual impar debe estar antes, pero impar llama a par: esto se llama recursión indirecta
• En el lenguaje C, debemos declarar las variables, los tipos y las funciones antes de usarlas.
• ¿Como haríamos en este caso?
Declaración anticipada • En realidad, C no necesita
conocer TODA la función antes de que sea usada, sino solamente su cabecera: nombre, tipo de retorno y parámetros.
• La solución es entonces incluir la cabecera antes de su uso.
• La declaración anticipada puede usarse cuando uno quiera, sin necesidad que se trata de funciones recursivas indirectas, pues a veces facilita la lectura de los programas
• Dibujar el estado de la pila para la llamada impar(7) cuando se llega al caso base.
Manos Dibujando Maurits Cornelius Escher (1948)
Recursión e Iteración
• La recursión es una herramienta poderosa pero ocupa muchos recursos en espacio y en tiempo.
• La recursión es una herramienta de repetición mucho mas poderosa que la iteración, debido a que la iteración funciona a nivel de bloque básico (lo que se repiten son un conjunto de sentencias acabadas con un GOTO), en cambio en la recursión se repite la función completa.
• Asi como es importante «salir del bucle», no quedarnos «colgados», en la recursión debemos garantizar el camino de regreso.
Recursión e Iteración
“Iterar es humano, ‘recursivar’ es divino” dijo
L. Peter Deutsch
Recursión e Iteración
“Iterar es humano, ‘recursivar’ es diabólico” digo
Yo!
De recursivo a iterativo
• Para toda función recursiva existe un algoritmo iterativo.
• No siempre es sencillo encontrarlo… aunque hay métodos que nos ayudan…
Recursivo es mas fácil de pensar
• Una ventaja de los recursivos es que es mas sencillo de pensar… (y mas bello a veces)
• Por ejemplo: pensamos en una función recursiva que calcule el número de bits necesario para representar un número entero. – Caso base: para representar el número 0 o el
número 1 necesitamos un bit
– Caso general: para representar el número n necesitamos un bit mas que para representar el número n/2, no? (la división es entera)
Recursivo: número de bits necesario para representar el número n
Fibonacci recursivo
• Un mal ejemplo:
Fibonacci recursivo
• En la versión recursiva, por cada llamada a función hay dos llamadas a la función, cada una de las cuales genera como mucho otras dos llamadas y así sucesivamente: es decir, el número de llamadas crece de forma exponencial con n, es decir, crece muy rápidamente. Es del orden 2n.
Fibonacci iterativo
• En la versión iterativa, el número de pasos es proporcional a n, es decir, crece linealmente con la entrada n. (se agrega una iteración mas)
• Por eso la versión iterativa es mejor que la recursiva, aunque no estamos diciendo que sea la mejor solución… podría haber alguna otra mejor.
Torres de Hanoi
• Reglas:
– Solo podemos mover el disco superior del montón.
– El disco superior debe moverse de una aguja a otra de tal manera que jamás quede debajo de él un disco de mayor tamaño.
Torres de Hanoi
• Para pasar el primer disco a la aguja final, las dos últimas situaciones deben ser las siguientes:
• Es decir, para resolver Hanoi(4, aguja inicial, aguja final), debemos: – resolver Hanoi(3, aguja
inicial, aguja libre) – Mover disco (aguja inicial,
aguja final) – Resolver Hanoi(3, aguja
libre, aguja final)
Hanoi
Hanoi
• El problema de Hanoi… es hacerlo iterativo. ¿Alguien se atreve?
Problemas Recursivos
Dibujando fractales, próximamente…
• Los fractales son objetos cuya estructura se repite a diferentes escalas.
• Se definen mediante simples algoritmos recursivos…
• Cuando sepamos dibujar, dibujaremos fractales usando recursión…