Recursividad.

Unidad II.- Recursividad.
2.1 Concepto de recursividad. 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 parrafo muestra una función, expresada con palabras, que calcula 8-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 informatica. Muchos algoritmos se pueden describir mejor en terminos 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 progrma no ha de continuar ejecutandose indefinidamente, un procedimiento recursivo ha de tener las dos siguientes propiedades:

para que la definicion no sea circular. La parte recursiva y la condición de terminación siempre existen. llamado criterio base. el argumento de la funcion debe acercarse mas al valor base. Indirecta: Cuando se definen una serie de subprogramas usándose unos a otros. (2) Cada vez que el procedimiento se llame a si mismo (directa o inderectamente). Tipos. debe estar mas cerca del criterio base. por el que el procedimiento no se llama asi mismo. Un procedimiento recursivo con estas dos propiedades se dice que esta bien definido. 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. Una funcion recursiva con estas dos propiedades se dice tambien que esta bien definida. Podemos distinguir dos tipos de recursividad: • • Directa: Cuando un subprograma se llama a si mismo una o mas veces directamente. otra iterativa o no recursiva y un acondición de terminación. De nuevo. . En cambio la parte no recursiva puede coincidir con la condición de terminación. llamados valores base. Características. Un algoritmo recursivo consta de una parte recursiva. Ventajas e inconvenientes. Similarmente. debe tener las dos siguientes propiedades: (1) Debe haber ciertos argumentos. una funcion se dice que esta definida recursivamente si la definicion de la funcion se refiere a si misma. (2) Cada vez que la funcion se refiera a si misma.(1) Debe existir un cierto criterio. para los que la funcion no se refiera a si misma. Si no se cumple esta condición el programa no parará nunca.

Normalmente. En muchos casos.Text. sencilla y elegante. favoreciendo la resolución de problemas de manera natural. una solución recursiva es menos eficiente en términos de tiempo de computadora que una solución iterativa debido al tiempo adicional de llamada a procedimientos. Esta característica permite a un procedimiento recursivo repetirse valores diferentes de parámetros. y facilidad para comprobar y convencerse de que la solución del problema es correcta.Clear().La principal ventaja es la simplicidad de comprensión y su gran potencia. Por esta razón la recursion (recursividad) es una herramienta muy potente para la resolución de problemas de programación. la recursion permite especificar una solución mas simple y natural para resolver un problema que en otro caso seria difícil.Text. int fin = 0. System.2 Procedimientos recursivos. System.Drawing. que utiliza bucles y pilas para almacenar las variables.Items. Un procedimiento o función recursiva es aquella que se llama así misma. La recursion es una alternativa a la iteración muy elegante en la solución de problemas. . System. System. El principal inconveniente es la ineficiencia tanto en tiempo como en memoria. namespace WindowsApplication1 { public partial class Recursividad : Form { public Recursividad() { InitializeComponent().ToString()).Forms. using using using using using using using System.Parse(textBox4. EventArgs e) { fin = int. dado que para permitir su uso es necesario transformar el programa recursivo en otro iterativo. } double r. System.Data. especialmente si estos tienen naturaleza recursiva. System. private void button1_Click(object sender.ComponentModel. En el siguiente ejemplo se muetra un procedimiento recursivo. 2.Collections.Windows.Generic. listBox1.

. Esta idea puede servir de ayuda para la definición de conceptos matematicos.ToString()) * (fin * fin) + int. El concepto de la recursividad es muy importante en programación.Parse(textBox5.ToString()) * fin + int. Mediante una definición finita hemos representado un conjunto infinito.Parse(textBox1.Add("x\ty").Add(fin.ToString()). fin++. Cuando el código F tiene una sentencia que involucra a F.Parse(textBox2. El siguiente número de un número natural es otro numero natural.ToString() + "\t" + r.Text.Items. la definición del conjunto de los numeros naturles es aque conjunto en el que se cumplen las siguientes caracteristicas: • • 0 es un número natural.Text. La recursividad es una herramienta muy eficaz para resolver diversos tipos de problemas existen muchos algoritmos que se describiran mejor en terminos recursivos. se tiene que existen diferentes tipos de recursión: Recursión directa.ToString()). evaluar().ToString())) { r = int. evaluar().Text. } } } } Mecánica de recursión. Dentro de la teoría de la recursión.Text. Un objeto recursivo es aquel que forma parte de si mismo. } //Procedimiento recusivo public void evaluar() { while (fin <= int. Asi.Items.listBox1.Parse(textBox3. listBox1.

Recursión múltiple. } int impar(int n) { if (n == 0) return 0. } A continuación se expone otro ejemplo de programa que utiliza recursión indirecta. Se puede transformar con facilidad en algoritmos iteractivos. int par (int n) { if (n==0) return n+1.Recursión indirecta o cruzada Cuando la función F involucra una función G que invoca a la ves una función H.. int par(int n). Por ejemplo: si hacemos par(2) devuelve 1 (cierto). hasta que se involucra la función F. resultando más difícil de transformar a iteractiva. return impar(n-1). return par(n-1). Poe ejemplo el algoritmo de Fibonacci. y así sucesivamente. return par(n-1).. Si hacemos impar (4) devuelve 0 (falso).Se da cuando hay más de una llamada a sí misma dentro del cuerpo de la función. } Recursión simple. Por ejemplo el algoritmo de Par o impar. Cabe mencionar que existen otros métodos mucho más sencillos para determinar la solución a este problema. int par(int n) { if (n == 0) return 1. y nos dice si un número es par o impar. return impar(n-1). int fibo(int n) { if (n<=1) return 1 return fibo(n-1) + fibo(n-2) } .Aquella en cuya función solo aparece una llamada recursiva. int impar(int n) if (n==0) return 0. basta con determinar el resto de la división entre dos. int impar(int n).

int n) { if (m==0) return n+1 if (n=00) return Ack(n-1. se provocan las siguientes operaciones: 1.En algunos de los argumentos de la llamada hay una nueva llamada a sí misma. Al terminar la función. 1) return Ack(m-1. 4. la definición recursiva debe incluir un componente base (condición de salida ) en el que f(n) se define directamente (es decir..1.Parte de la memoria donde se guardan las instrucciones del programa en código máquina. Cuando se trabaja llamados a la ejecución de las funciones. la memoria de la computadora hace uso de una pila de recursión. . Almacenar los parámetros de la función y sus valores de pila. Segmento de datos. n-1)). 2. Debe existir una <> de la secuencia de llamadas recursivas.4. Segmento de código. 4.5. Cualquier algoritmo que genere una secuencia de este tipo no terminará nunca..3.Recursión anidada. Montículo. Reservar espacio en la pila para los parámetros de la función y sus variables locales.. se libera la memoria asignada en la pila y se vuelve a la instrucción actual. Funciones mutuamente recursivas. Al estar trabajando con recursividad. En consecuencia. } Un requisito para que un algoritmo recursivo sea correcto es que no genere una secuencia infinita de llamadas sobre sí mismo... Pila de programa. 2. no recursivamente) para uno o más valores de n. 3. 3. Ack(m.. Por ejemplo la función de Ackerman: int Ack(int m. la cual se divide de manera lógica en 4 segmentos: 1.Parte de la memoria destinada a las variables dinámicas. Guardar en la pila la dirección de la línea de código desde donde se ha llamado a la función.Parte de la memoria destinada a almacenar las variables estáticas.parte destinada a las variables locales y parámetros de la función que está siendo ejecutada.

se llama a sí mismo con valores de parámetros modificados que describen un subproblema cercano a esa forma. y así para siempre. Una recursión infinita ocurre si la etapa de recursión no reduce el problema en cada ocasión de modo que converja sobre el caso base o condición de la salida. La ciencia de la computación hace tiempo que descubrió que se puede reemplazar a un método que utiliza un bucle para realizar un cálculo con un método que se llame repetidamente a sí mismo para realizar el mismo cálculo. Un programa llama a un método con uno o más parámetros que describen un problema. la llamada el método original se completa. dicha función se ejecutará hasta que la computadora agote la memoria disponible y se produzca una terminación anormal del programa. . si el tipo de retorno del método no es void. Si el método detecta que los valores no representan la forma más simple del problema. En realidad. Recursión infinita La iteración y la recursión pueden producirse infinitamente. en cuyo caso el método simplemente retorna. Esta actividad continúa hasta que el método detecta la forma más simple del problema.Pero cuando se trabaja con funciones recursivas. y posiblemente se devuelve un valor. 3. El flujo de control de una función recursiva requiere de tres condiciones para una terminación normal. 2. se provoca además lo siguiente: 1. En la práctica. larecursión infinita significa que cada llamada recursiva produce otra llamada recursiva y esta a su vez otra llamada recursiva. En ese momento se crean en la pila nuevos parámetros y variables locales. En algún punto. El hecho de que un método se llame repetidamente a sí mismo se conoce como recursion. La recursión trabaja dividiendo un problema en subproblemas. posiblemente con un valor. Se crean más copias hasta llegar a la primera llamada (ultima en cerrarse). La pila de llamadas a método empieza a desbobinarse como una llamada a método anidada para ayudar a completar una evaluación de expresión. Un bucle infinito ocurre si la prueba o test de continuación del bucle nunca se vuelve falsa. La función se ejecutará normalmente hasta la llamada a sí misma. El nuevo ejemplar de función comienza a ejecutarse.

afrimar que la ejecución de un programa recursivo va a ser mas lenta y menos eficiente que el programa iterativo que soluciona el mismo problema. de X a Y. El número de movimientos es M3(n) = 2n−1. aunque. como se puede demostrar fácilmente por inducción sobre el número de discos. parece más la definición de un problema que su resolución. como vimos antes. de longitud mínima) posible. usando como auxiliar el poste Y. Se cumple para n = 1 M3(1) = 1 = 21−1. Traslada la torre 1…n−1 usando este mismo algoritmo. La secuencia de movimientos que produce este algoritmo es la única solución óptima (o sea. usando como auxiliar X. Por ejemplo. lo único que hace es especificar unos pasos inevitables. por lo tanto. se cumple para d+1 . De esta manera se puede eliminar la recursion de aquellas partes de los programas que se ejecutan más frecuentemente. Los procedimientos recursivos se pueden convertir en no recursivos mediante la introducción de una pila y asi emular las llamadas recursivas. etc. Se puede. Traslada la torre 1…n−1 usando este mismo algoritmo. Ejemplo de mecánica de la recursividad Las torres de Hanoi Algoritmo para trasladar la torre 1…n del poste X al poste Z. y para ello es obligatorio llevar antes la torre 1…n a B. usando como auxiliar Z. Lleva el disco n de X a Z.Cuando no utilizar recursividad. en la mayoria de los lenguajes de programación las llamadas recursivas a procedimientos o funciones tienen un coste de tiempo mucho mayor que sus homologos iterativos. para resolver el puzzle es obligatorio llevar el disco n de A a C. a veces. Si n = 1. lleva el disco 1 de X a Z y termina. Si eres como yo tendrás que implementarlo en un lenguaje de programación concreto para convencerte de que funciona. Este algoritmo siempre me ha parecido sorprendente. En realidad. La solucion recursiva de ciertos problemas simplifica mucho la estructura de los programas. Como contrapartida. la sencilles de la estructura recursiva justifica el mayor tiempo de ejecucion. Si se cumple para n. de Y a Z.

más un movimiento del disco n+1. estando encapsulados dentro de una función. que hacen uso de ciclos while. pero son difíciles de aplicar para un ser humano.744. y cuando sí se conoce. Si los bramanes de Benarés cambiaran un disco de sitio cada segundo necesitarían más de quinientos ochenta mil millones de años para terminar su tarea. Son recursivos aquellos algoritmos que. El concepto de recursividad va ligado al de repetición.709. Sin embargo. en contraposición a los algoritmos iterativos. unas cuarenta veces la edad del Universo.Al ejecutarse el algoritmo para n+1 se llama a sí mismo dos veces para n. etc. 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: . La alternativa a los algoritmos recursivos son los iterativos. existen varios algoritmos iterativos muy simples. en los que no hay llamadas a sí mismo. Así que M3(n+1) = 2 × M3(n) + 1 = 2 × (2n−1) + 1 = 2n+1−2+1 = 2n+1−1. Para que una definición recursiva sea válida. Para n = 64. do-while. suele ser mucho más complicada que la versión recursiva. la referencia a sí misma debe ser relativamente más sencilla que el caso considerado. en el caso de la Torre de Hanoi. Los algoritmos recursivos funcionan bien con ordenadores. Si intentas resolver la torre de ocho discos aplicando el método descrito es fácil que te pierdas a no ser que vayas tomando notas de por dónde vas. for. sino uno o varios bucles. Muy a menudo no existe o no se conoce una alternativa iterativa para un algoritmo recursivo. de 264−1 = 18.551.446. Para n = 8 el número de movimientos es de 28−1 = 255.073.615. en el sentido de que consumen bastante memoria (y es que ellos también necesitan «tomar notas»). son llamados desde ella misma una y otra vez. Transformación de algoritmos recursivos a iterativos. Incluso para los ordenadores los algoritmos recursivos suelen ser «poco económicos». Algo es recursivo si se define en términos de sí mismo (cuando para definirse hace mención a sí mismo).

Text. EventArgs e) { .Collections.Drawing. 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. x) * (1 + (x/100)).Windows. System. namespace WindowsApplication1 { public partial class Form1 : Form { class cap_recursivo { public float capital(float m. n . } } } public Form1() { InitializeComponent(). pero están más próximas al caso base. int n. float x) { if (n == 0) { return m. b). Parte puramente recursiva: Relaciona el resultado del algoritmo con resultados de casos más simples.Forms.Data.Generic. EventArgs e) { } private void button1_Click(object sender. Caso trivial. } else { return capital(m. Codigo Recursivo using using using using using using using System. System. Se hacen nuevas llamadas a la función. Evita la continuación indefinida de las partes recursivas. private void Form1_Load(object sender. System. System.ComponentModel. System.a). System.1.

Drawing.Text.Text = int.Generic.Windows.Data. System. System.Collections. namespace WindowsApplication7 { public partial class Form1 : Form { class cap { public float capital(float m. System. System.Forms.capital()). } . System.cap sayo = new cap(). EventArgs e) { } } } Diseño Codigo Iterativo using using using using using using using System. } private void label4_Click(object sender. float x) { if (n == 0) { return m. int n.ComponentModel. System. label4.Parse(sayo.

} } } public Form1() { InitializeComponent(). label4.Parse(sayo. n . //return capital(m. b > 0.capital()). for (int b = n. EventArgs e) { } private void button1_Click(object sender. b--) { m = m + (x * m).(m ) + } } return m.else { //x = x / 100. x = x / 100. EventArgs e) { } } } . } private void label4_Click(object sender.Text = int. EventArgs e) { cap sayo = new cap(). } private void Form1_Load(object sender.float inn.1. x) * (1 + (x / 100)). //x = x * m.1. //n = n . //m = x + m.

No importa si va primero o despues. Un ejemplo en una función genérica seria este: .Diseño Explicacion Este programa lo que hace es calcular el interes de un monto inicial de acuerdo a cuanto se pidio prestado. Recursividad en diseño. y la iteraria es de forma seguida y larga. los dos tipos llegan al mismo objetivo. La forma recursiva se vuelve a llamar. Al pasar el primer año. y al segundo año o mas se calcula el monto total + interes y asi sucesivamente hasta terminar el periodo del prestamo. Dependiendo del método que utilicemos para diseñar la representación gráfica 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. son dos diferentes metodos de hacer la misma accion. Un procedimiento recursivo es aquel que se llama a sí mismo. El recursivo manda a llamar la misma funcion dentro de si misma y iterativo hace todo el trabajo seguido. se calcula el monto inicial + interes = monto total. osea que vuelve a hacer el procedimiento dentro de si misma. La recursividad en diseño se refiere a la manera de cómo representar los procedimientos recursivos al momento de diseñar los programas. para poder funcionar tiene que tener una condición de salida que del número de veces que se va a llamar a sí mismo el procedimiento. a cuanto porcentaje de interes y el tiempo por el que fue prestado.

pero se pueden utilizar ciclos siempre asegurándonos de que nos den salida en algún momento. o. y al no cumplirse debe apuntar al siguiente paso en el procedimiento o al final o viceversa. } Fin. u} Seudocódigo: . Condición ( ) { Llamada al metodo1.METODO1 { Procedimiento x. e. i. Lo importante y que tenemos que tomar en cuenta es que la si se cumple el criterio para llamar el procedimiento hay que apuntar a el inicio del método. } En un diagrama seria algo así: NOTA: Estos son dos ejemplos en ambos utilizamos una condición. Ejemplo: Diseñar un programa que despliegue el contenido de un arreglo el siguiente arreglo: {a.

etc) de tal forma que dentro de un subprograma recursivo hay una o más llamadas a él mismo. En el constructor mandamos llamar al método despliegue. De esta forma. FIN-SI FIN Generalmente. . llamará al método despliegue. Y listo al abrir nuestro programa vamos a desplegar dentro del listbox el arreglo mediante la recursividad. de igual naturaleza que el original. SINO Factorial = n * Factorial(n-1).i++) dentro del cual se hará el despliegue en el índice i del arreglo vocales b. En esa situación diremos que estamos ante un caso base de la recursividad. Un algoritmo recursivo es un algoritmo que se define en términos de sí mismo. FUNCIÓN Factorial(n) INICIO SI (n<2) ENTONCES Factorial = 1. suficientemente manejable como para resolverlo de forma no recursiva). Un ciclo for (int i=0. subrutinas. llegará un momento en que su resolución sea más o menos trivial (o.1. Después creamos el método despliegue. pero de un tamaño menor que N. cada nueva ejecución recurrente del mismo se planteará sobre problemas. al menos. Complejidad en los algoritmos recursivos. al ir reduciendo progresivamente la complejidad del problema a resolver. Son implementados en forma de subprogramas (funciones. 2.i 4. El cual contendrá: a. si la primera llamada al subprograma se plantea sobre un problema de tamaño u orden N. Creamos el arreglo que contendrá los elementos (vocales) 3. Para ver un programa visual de recursividad ver el tema recursividad. Creamos la forma que contendrá una listbox para despliegue. procedimientos. 4.

Sign up to vote on this title
UsefulNot useful