Recursividad

16
Definición Recursividad Capacidad que tiene los métodos de invocarse así mismos, esta es una potente herramienta en la informática. Con esta herramienta muchos algoritmos pueden simplificarse significativamente. 4.2 Procedimientos Recursivos. La recursividad es una técnica de programación importante. Se utiliza para realizar una llamada a una funcion desde la misma funcion. Como ejemplo útil se puede presentar el cálculo de números factoriales. Él factorial de 0 es, por definición, 1. Los factoriales de números mayores se calculan mediante la multiplicación de 1 * 2 * …, incrementando el número de 1 en 1 hasta llegar al número para el que se está calculando el factorial. El siguiente párrafo muestra una función, expresada con palabras, que calcula un factorial. “Si el número es menor que cero, se rechaza. Si no es un entero, se redondea al siguiente entero. Si el número es cero, su factorial es uno. Si el número es mayor que cero, se multiplica por él factorial del número menor inmediato.” Para calcular el factorial de cualquier número mayor que cero hay que calcular como mínimo el factorial de otro número. La función que se utiliza es la función en la que se encuentra en estos momentos, esta función debe llamarse a sí misma para el número menor inmediato, para poder ejecutarse en el número actual. Esto es un ejemplo de recursividad.

description

Tema de estructura de datos

Transcript of Recursividad

Page 1: Recursividad

Definición Recursividad

Capacidad que tiene los métodos de invocarse así mismos, esta es una potente herramienta en la informática.

Con esta herramienta muchos algoritmos pueden simplificarse significativamente.

4.2 Procedimientos Recursivos.

La recursividad es una técnica de programación importante. Se utiliza para realizar una llamada a una funcion desde la misma funcion. Como ejemplo útil se puede presentar el cálculo de números factoriales. Él factorial de 0 es, por definición,

1. Los factoriales de números mayores se calculan mediante la multiplicación de 1 * 2 * …, incrementando el número de 1 en 1 hasta llegar al número para el que se está calculando el factorial.

El siguiente párrafo muestra una función, expresada con palabras, que calcula un factorial.

“Si el número es menor que cero, se rechaza. Si no es un entero, se redondea al siguiente entero. Si el número es cero, su factorial es uno. Si el número es mayor que cero, se multiplica por él factorial del número menor inmediato.”

Para calcular el factorial de cualquier número mayor que cero hay que calcular como mínimo el factorial de otro número. La función que se utiliza es la función en la que se encuentra en estos momentos, esta función debe llamarse a sí misma para el número menor inmediato, para poder ejecutarse en el número actual. Esto es un ejemplo de recursividad.

La recursividad es un concepto importante en informática. Muchos algoritmos se pueden describir mejor en términos de recursividad.

Supongamos que P es un procedimiento que contiene una sentencia de Llamada a si mismo o una sentencia de Llamada a un segundo procedimiento que puede eventualmente llamar de vuelta al procedimiento original P. Entonces P se dice que es u procedimiento recursivo. Como el programa no ha de continuar ejecutándose indefinidamente, un procedimiento recursivo ha de tener las dos siguientes propiedades:

(1) Debe existir un cierto criterio, llamado criterio base, por el que el procedimiento no se llama así mismo.

Page 2: Recursividad

(2) Cada vez que el procedimiento se llame a si mismo (directa o indirectamente), debe estar más cerca del criterio base.

Un procedimiento recursivo con estas dos propiedades se dice que está bien definido.

Similarmente, una función se dice que esta definida recursivamente si la definición de la funcion se refiere a si misma. De nuevo, para que la definicion no sea circular, debe tener las dos siguientes propiedades:

(1) Debe haber ciertos argumentos, llamados valores base, para los que la funcion no se refiera a si misma.

(2) Cada vez que la funcion se refiera a si misma, el argumento de la funcion debe acercarse mas al valor base.

Una funcion recursiva con estas dos propiedades se dice tambien que esta bien definida.

Tipos.

Podemos distinguir dos tipos de recursividad:

Directa: Cuando un subprograma se llama a si mismo una o mas veces directamente. Indirecta: Cuando se definen una serie de subprogramas usándose unos a otros.

Características.

Un algoritmo recursivo consta de una parte recursiva, otra iterativa o no recursiva y un acondición de terminación. La parte recursiva y la condición de terminación siempre existen. En cambio la parte no recursiva puede coincidir con la condición de terminación. Algo muy importante a tener en cuenta cuando usemos la recursividad es que es necesario asegurarnos que llega un momento en que no hacemos más llamadas recursivas. Si no se cumple esta condición el programa no parará nunca.

Ventajas e inconvenientes. La principal ventaja es la simplicidad de comprensión y su gran potencia, favoreciendo la resolución de problemas de manera natural, sencilla y elegante; y facilidad para comprobar y convencerse de que la solución del problema es correcta. El principal inconveniente es la ineficiencia tanto en tiempo como en memoria, dado que para permitir su uso es necesario transformar el programa recursivo en otro iterativo, que utiliza bucles y pilas para almacenar las variables.

4.3 Mecánica Recursión.

Page 3: Recursividad

La mecánica de la recursividad está basada en una “pila”. Cuando un módulo recursivo se está ejecutando se crea en la memoria de la computadora una pila donde se almacenan los valores de los parámetros y de las variables locales del módulo. Si el módulo es función también se guarda en la pila el valor que adquiere la misma.

Para cada llamada del módulo se almacenan en la pila los nuevos valores de los parámetros y de las variables locales, creándose un nuevo “registro de activación”. De tal forma que, la pila de recursión está formada por registros de activación. Al terminar una llamada al módulo, es decir, cuando se cumple la definición base, se libera (sale) el registro de activación que se encuentra en el tope de la pila. De esta forma es como puede “recordar” qué valores tenían los parámetros y las variables locales en la llamada anterior.

Si observamos el proceso que seguimos para calcular 4! vemos que el valor de n fue cambiando conforme fuimos entrando en recursión y que al salir de recursión necesitábamos recordar el valor que tenía n en la expresión anterior. Esto quiere decir que los valores que fue adquiriendo n fueron entrando a la pila.

No sólo debe recordar los valores que tenían los parámetros y las variables locales al realizarse la correspondiente llamada al módulo sino que también tiene que recordar qué instrucción debe realizar al terminar esa llamada. De tal forma que los registros de activación están compuestos básicamente de:

1. Instrucción a la que debe regresar el control una vez terminada la ejecución actual del módulo.

2. Todos los parámetros y variables locales del módulo.

3. Si el módulo recursivo es una función el valor que adquiere la misma, ya que éste se debe regresar.

Para hacer la representación de la pila de recursión numeramos las instrucciones a las que debe regresar el control una vez terminada la ejecución del módulo recursivo y estos valores son los que ponemos en la pila.

4.4 Transformación Algoritmos Recursivos a Iterativos

El concepto de recursividad va ligado al de repetición. Son recursivos aquellos algoritmos que, estando encapsulados dentro de una función, son llamados desde ella misma una y otra vez, en contraposición a los algoritmos iterativos, que hacen uso de ciclos while, do-while, for, etc.

Algo es recursivo si se define en términos de sí mismo (cuando para definirse hace mención a sí mismo). Para que una definición recursiva sea válida, la referencia a sí misma debe ser relativamente más sencilla que el caso considerado.

Page 4: Recursividad

Ejemplo: definición de nº natural:

→ el N º 0 es natural

→ El Nº n es natural si n-1 lo es.

En un algoritmo recursivo distinguimos como mínimo 2 partes:

a). Caso trivial, base o de fin de recursión:

Es un caso donde el problema puede resolverse sin tener que hacer uso de una nueva llamada a sí mismo. Evita la continuación indefinida de las partes recursivas.

b). Parte puramente recursiva:

Relaciona el resultado del algoritmo con resultados de casos más simples. Se hacen nuevas llamadas a la función, pero están más próximas al caso base.

4.5 Recursividad en Diseño

Un procedimiento recursivo es aquel que se llama a si mismo, para poder funcionar tiene que tener una condición de salida que de el numero de veces que se va a llamar a si mismo el procedimiento.

La recursividad en diseño se refiere a la manera de cómo representar los procedimientos recursivos al momento de diseñar los programas.

Dependiendo del método que utilicemos para diseñar la representación grafica de la recursividad va a ser diferente sin embargo el procedimiento va a ser similar ya que el fin es el mismo poner una condición que nos diga si llamamos al método o que nos mande terminarlo.

En un diagrama seria algo así:

4.6 Complejidad Algoritmos Recursivos

Un algoritmo recursivo es un algoritmo que se define en términos de sí mismo. Son implementados en forma de subprogramas (funciones, subrutinas, procedimientos, etc) de tal forma que dentro de un subprograma recursivo hay una o más llamadas a él mismo.

FUNCIÓN Factorial(n)

Page 5: Recursividad

INICIO

SI (n<2) factorial =" 1;" factorial =" n">

Bibliografía

Consulta a libros:

Autores:•

Alfred V. Aho•

John E. Hopcroft•

Jefrey D. Ullman

Libro:

Estructura De Datos Y Algoritmos

Editorial: Addison-Wesley Iberoamericana

Edición: Revisada

REFERENCIAS DE INTERNET

http://arco.esi.uclm.es/~david.villa/pensar_en_C++/products/vol1/ch03s02s09.html

Definición

Recursión es una técnica de programación en el cual un método puede llamarse a sí mismo. La recursión es muy interesante y una técnica efectiva en programación ya que puede producir algoritmos cortos y eficientes.

Algo es recursivo si se define en términos de sí mismo (cuando para definirse hace mención a sí mismo).

Si la invocación de un subprograma (función o subrutina) se produce desde el propio subprograma se dice que se trata de un subprograma recursivo.

Un método recursivo es un método, directa o indirectamente, se hace una llamada a sí mismo.

La recursión consiste en el uso de métodos recursivos.

Page 6: Recursividad

2.2 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);

}

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);

}

Analizando el concepto de recursividad y su clasificación, puede indicar que es un procedimiento infinito, que solo se detendrá en el momento que se agote la memoria, generando un error de programación y la interrupción del mismo.

Page 7: Recursividad

Pero esto no es así, ya que debe existir un elemento que indica el retorno de un resultado concreto y no el retorno de la llamada al método recursivo o recurrente.

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

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)

Page 8: Recursividad

2 2*factorial(1)

1 1*factorial(0)

0 1

En general el proceso es (4*factorial(3*factorial(2*factorial(1*factorial(0)))))

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

De tal forma que podemos determinar que:

1 si n = 1 paso básico

n + (n-1) si n > 1 paso inductivo o proceso recursivo

//5+suma(4+suma(3+suma(2+suma(1))))

Imprimir de manera recursiva la serie de fibonnaci

La serie de fibonacci trabaja de la siguiente forma:

Paso 1: Si tenemos dos semillas formadas por s1=0 y s1=1

0 1

Paso 2. Se suman para obtener el resultado

0 1 1

Ahora la semilla 1 se queda con el valor de la semilla 2 y el resultado se asigna a la semilla 2 y se vuelve a realizar el paso 2. De tal forma que la serie queda de la siguiente forma:

0 1 1 2 3 5 8 13 21 34 55 89 ………….

Fibonnacci de manera recursiva

Page 9: Recursividad

Fibonacci(0,1,21)=1

Fibonacci(1,1,21)=2

Fibonacci(1,2,21)=3

Fibonacci(2,3,21)=5

Fibonacci(3,5,21)=8

Fibonacci(5,8,21)=13

Fibonacci(8,13,21)=21

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

Realizar el producto de un número por sumas sucesivas de manera recursiva.

El producto de un número (3*9) se realiza de la siguiente forma:

1 2 3 4 5 6 7 8 9

Page 10: Recursividad

3+3+3+3+3+3+3+3+3

cant =0 0 caso base

n+(cant-1) proceso recursivo

Realizar de manera recursiva como calcular un número en binario a través de desplazamientos sucesivos

La manera de convertir a binario un número es de la siguiente forma:

Si es para un número de ocho bits el rango de valores abarca de 0 a 255, si es en ese caso se debe de utilizar una máscara de 0x80. Que representa a un número en binario 10000000 es decir el último bit en 1.

Se realiza una operación (AND)& a nivel de bits del número a convertir y si el resultado es cero entonces ese representa al primer valor del número en binario y si no es cero entonces este lo representa.

Posterior a esto se desplaza el bit una posición a la derecha y se vuelve a hacer la misma operación & y nos vuelve a dar como resultado 0 o un numero diferente de 0.

Este proceso se repite hasta que se llegue hasta el final # de bits. En este caso 8 iteraciones.

Ejemplo:

Numero a convertir es 13

La máscara es 0x80=10000000

13 en binario es 00001101

La máscara es 10000000

Resultado & 00000000 da el primer valor del número convertido 0

Se repite el mismo proceso pero con el bit 1 de la máscara recorrido una posición a la derecha.

Page 11: Recursividad

13 en binario es 00001101

La máscara es 01000000

Resultado & 00000000 da el primer valor del número convertido 0

13 en binario es 00001101

La máscara es 00100000

Resultado & 00000000 da el primer valor del número convertido 0

13 en binario es 00001101

La máscara es 00010000

Resultado & 00000000 da el primer valor del número convertido 0

13 en binario es 00001101

La máscara es 00001000

Resultado & 00001000 da el primer valor del número convertido 1

13 en binario es 00001101

La máscara es 00000100

Resultado & 00000100 da el primer valor del número convertido 1

13 en binario es 00001101

La máscara es 00000010

Resultado & 00000000 da el primer valor del número convertido 0

13 en binario es 00001101

La máscara es 00000001

Page 12: Recursividad

Resultado & 00000000 da el primer valor del número convertido 1

Realizar un procedimiento recursivo para calcular la suma de un vector de n números.

* Realizar un procedimiento que imprima de manera recursiva los numeros del 1al 10

* Realizar un procedimiento que imprima de manera recursiva la tabla del 9

*Realizar un procedimiento que encuentre el numero mayor de un vector de n numeros enteros de manera recursiva.

Primero debemos decir que la recursividad no es una estructura de datos, sino que es una técnica de programación que nos permite que un bloque de instrucciones se ejecute n veces. Remplaza en ocasiones a estructuras repetitivas.

Este concepto será de gran utilidad para el capítulo de la estructura de datos tipo árbol.

La recursividad es un concepto difícil de entender en principio, pero luego de analizar diferentes problemas aparecen puntos comunes.

En Java los métodos pueden llamarse a sí mismos. Si dentro de un método existe la llamada a sí mismo decimos que el método es recursivo.

Cuando un método se llama a sí mismo, se asigna espacio en la pila para las nuevas variables locales y parámetros.

Al volver de una llamada recursiva, se recuperan de la pila las variables locales y los parámetros antiguos y la ejecución se reanuda en el punto de la llamada al método.