recursión como herramienta en resolución de problemas ... · ejemplo matemática no trivial lo! t...

5
Recursión como herramienta en resolución de problemas computacionales Modularidad ! Es común dividir los algoritmos en módulos ! Cada módulo lleva a cabo cierta funcionalidad ! Muchas veces los módulos sirven para más de un algoritmo, o sea, se reutilizan ! Gente publica bibliotecas de tales módulos, que llamamos “librerías” por anglismo ! El módulo más pequeño es una subrutina Subrutinas ! Métodos auxiliares ! Toman uno o varios parámetros de tipos predefinidos ! Ejecutan su propio código a base de los parámetros recibidos ! Al recibir punteros, pueden modificar variables de la parte del programa que llamó a la subrutina ! Producen (opcionalmente) un valor de salida Ejemplos ! Frecuentemente usamos subrutinas de las bibliotecas estándares de ANSI-C para la siguiente funcionalidad ! Impresión en el terminal (stdio.h) ! Lectura de datos del teclado (stdio.h) ! Operaciones matemáticas (math.h) ! Manipulación de cadenas de caracteres (string.h)

Upload: others

Post on 13-Jul-2020

6 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Recursión como herramienta en resolución de problemas ... · Ejemplo Matemática no trivial lo! T 1 T ( n 2T " n 2 # + n log n es ak =2g n = n 2 = n . 4 n k gn 2k − 1 k( 2g n

Recursión como herramienta en resolución

de problemas computacionales

Modularidad

! Es común dividir los algoritmos en módulos

! Cada módulo lleva a cabo cierta funcionalidad

! Muchas veces los módulos sirven para más de un algoritmo, o sea, se reutilizan

! Gente publica bibliotecas de tales módulos, que llamamos “librerías” por anglismo

! El módulo más pequeño es una subrutina

Subrutinas! Métodos auxiliares

! Toman uno o varios parámetros de tipos predefinidos

! Ejecutan su propio código a base de los parámetros recibidos

! Al recibir punteros, pueden modificar variables de la parte del programa que llamó a la subrutina

! Producen (opcionalmente) un valor de salida

Ejemplos

! Frecuentemente usamos subrutinas de las bibliotecas estándares de ANSI-C para la siguiente funcionalidad

! Impresión en el terminal (stdio.h)

! Lectura de datos del teclado (stdio.h)

! Operaciones matemáticas (math.h)

! Manipulación de cadenas de caracteres (string.h)

Page 2: Recursión como herramienta en resolución de problemas ... · Ejemplo Matemática no trivial lo! T 1 T ( n 2T " n 2 # + n log n es ak =2g n = n 2 = n . 4 n k gn 2k − 1 k( 2g n

Encadenados

! El método principal (main) puede llamar a subrutinas

! Luego, esas subrutinas pueden llamar a otras subrutinas

! Esas luego a otras

! Etcétera - no hay un límite fijo de “profundidad” de llamadas

Flujo de control

! Típicamente solamente una (sub)rutina de un programa específico puede estar en ejecución a la vez

! La ejecución simultánea de dos o más (sub)rutinas requiere programación paralela y múltiples núcleos y/o procesadores

! Se dice que la (sub)rutina en ejecución “tiene control” de la computadora

! Al terminar su ejecución, una subrutina devuelve el control de la computadora a la rutina que la llamó

Código en ANSI-C

#include <stdio.h> // biblioteca que incluye la rutina printf#include “pidevalor.h” // subrutina externa “nuestra”int computo(int v) { return (v % 2);}int main(int c, char** s) { // rutina principal int valor = pidevalor(5, 10); // llamada a subrutina printf(“%d\n”, computo(valor)); // llamadas a otras dos return 1; // salir del programa}

La implementación de pidevalor está en la página de asesorías

Ejecución del ejemplo

main pidevalor

computo printf

Page 3: Recursión como herramienta en resolución de problemas ... · Ejemplo Matemática no trivial lo! T 1 T ( n 2T " n 2 # + n log n es ak =2g n = n 2 = n . 4 n k gn 2k − 1 k( 2g n

Iteración! A veces es necesario realizar alguna computación de

manera repetida como componente del algoritmo

! Este código estará o adentro de un ciclo tal como es o se puede “vestir” como una subrutina

! Llamas repetidas de una subrutina o la ejecución de un bloque de código en un ciclo se conoce como iteración

! Ya lo usábamos en clase por ejemplo para generar potencias de dos y los números de Fibonacci

Números primos revisitadosrutina_principal { entero positivo n = valor de entrada; entero positivo i = 3; si (n % 2 == 0 y n > 2) { imprimir “no es primo”; salir del programa; } mientras (i < raiz_cuadrada(n)) { si (n % i == 0) { imprimir “ no es primo,”; salir del programa; } i += 2; } imprimir “resulta que es primo”; salir del programa;}

Caso especial

Iteración

Recursión

! Cuando una (sub)rutina llama a si misma, se dice que es recursivo

! Intentamos, por fines de ejemplo, esto para el caso de los números primos

! Vamos a ver muchos algoritmos recursivos en la segunda mitad de esta unidad de aprendizaje

Primos recursivos

primo(entero numero, entrada divisor) { si (divisor == 1) { devolver “verdad”; } en otro caso si (numero % divisor == 0) { devolver “falso”; } en otro caso { devolver primo(numero, divisor - 2); }}rutina_principal { si (primo(entrada, raiz_cuadrada(entrada)) { imprimir “resulta que es primo”; } en otro caso { imprimir “no es primo”; } salir del programa;}

Llamada recursiva

Rutina recursiva

Rutina principal

Page 4: Recursión como herramienta en resolución de problemas ... · Ejemplo Matemática no trivial lo! T 1 T ( n 2T " n 2 # + n log n es ak =2g n = n 2 = n . 4 n k gn 2k − 1 k( 2g n

Análisis asintótico revisitado

Algoritmos simples

Para analizar desde un pseudocódigo la complejidad,típicamente se aplica las reglas siguientes:

Asignación de variables simples toman tiempo O (1).Escribir una salida simple toma tiempo O (1).Leer una entrada simple toma tiempo O (1).

Algoritmos recursivos– p. 2

! Asignación de una variable toma tiempo constante

! Llamada a una rutina toma tiempo constante, y luego hay que tomar en cuenta los pasos que conlleva

! Escribir una salida y leer una entrada simple ambos toman tiempo constante

Análisis de algoritmos recursivos

! Típicamente hay que escribir una ecuación recursiva para poder correctamente caracterizar la cantidad de llamadas que se hará a la rutina recursiva

! Esto suele involucrar más matemáticas de lo que podemos acomodar en esta unidad de aprendizaje

! Vamos a ver algunos ejemplos sin meternos en cómo fueron resueltos

Ejemplo

Aplicación iterativa

Otra opcion es aplicar la ecuación recursiva de unamanera iterativa.Por ejemplo, con la ecuación diferencial

!

T (1) = c1,T (n) ! 2T

"n2

#

+ c2n.

obtenemos por aplicación repetida

T (n) ! 2T"

n2

#

+ c2n ! 2"

2T (n/4) + c2n2

#

+ c2n= 4T (n/4) + 2c2n ! 4 (2T (n/8) + c2n/4) + 2c2n= 8T (n/8) + 3c2n.

Algoritmos recursivos– p. 9

El resultado

De la condición 2k = n sabemos que

k = log n.

Entonces, con T (1) ! c1 obtenemos

T (n) ! c1n + c2n log n

o seaT (n) " O (n log n) .

Algoritmos recursivos– p. 11

Matemática no trivial

Ejemplo

Matemática no trivial

Estimación

Incluso se puede estimar la parte heterogénica en algunoscasos donde d no es multiplicativa.Por ejemplo, en

!

T (1) = 1T (n) = 3T

"n2

#

+ 2n1,5

d(n) = 2n1,5 no es multiplicativa, mientras n1,5 sóla lo es.

Algoritmos recursivos– p. 21

Análisis del ejemplo

Si tuvieramos que U(1) = 1, tendríamos una partehomogénica 3log n = nlog 3.En el caso U(1) = 1

2 tendríamos12n

log 3.En la parte heterogénica, el valor de U(1) no tiene ningúnefecto.=! a = 3 y b = 2=! d(b) = b1,5 " 2, 82=! d(b) < a=! La parte heterogénica es O

!

nlog 3"

.=! U(n) # O

!

nlog 3"

Con T (n) = 2U(n) =! T (n) # O!

nlog 3"

Algoritmos recursivos– p. 23

Page 5: Recursión como herramienta en resolución de problemas ... · Ejemplo Matemática no trivial lo! T 1 T ( n 2T " n 2 # + n log n es ak =2g n = n 2 = n . 4 n k gn 2k − 1 k( 2g n

Ejemplo

Matemática no trivial

Otro ejemplo

!

T (1) = 1T (n) = 2T

"n2

#

+ n log n

donde la parte homogénica es ak = 2log n = nlog 2 = n.

Algoritmos recursivos– p. 24

Asignación k = log n

2k!1k(k + 1) = 2log n!1 log n(log n + 1)

= 2log(n

2 )(log2 n + log n)= n

2 (log2 n + log n),

=! La parte heterogénica es O!

n log2 n"

.

Algoritmos recursivos– p. 26

Ejemplo

Matemática casi trivial pero larga

Método de expansión

Elmetodo de expansion facilita la computacióninvolucrada en abrir una ecuación recursiva.Ejemplo:

!

R(1) = 1R(n) = 2R(n ! 1) + n, donde n " 2.

Algoritmos recursivos– p. 27

Multiplicar y sumar

Multiplicamos por los coeficientes del lado izquiera y sumamos:R(n) = 2n!1R(1) + n + 2(n ! 1) + 4(n ! 2) + . . . + 2n!22= n + 2(n ! 1) + 4(n ! 2) + . . . + 2n!22 + 2n!1

=n!1!

i=0

2i(n ! i)

= 20 + . . . + 20" #$ %

n veces

+21 + . . . + 21" #$ %

n!1 veces

+22 + . . . + 22" #$ %

n!2 veces

+ . . . + 2n!1"#$%

1 vez

=n!1!

i=0

i!

j=0

2j =n!1!

i=0

(2i+1 ! 1) =n!1!

i=0

2i+1 !n!1!

i=0

1

= 2n+1 ! 2 ! n.

Algoritmos recursivos– p. 30

Método experimental

! Ustedes, en vez de analizar de esta manera, pueden estudiar experimentalmente la curva de tamaño de instancia versus número de pasos (igual como en el segundo proyecto)

! Luego ven visualmente desde su forma a cuál función de complejidad típica se acerca o que por lo menos esté acotado de manera asintótica