Professional Documents
Culture Documents
ALVARO MARTINEZ
Recursin
INTRODUCCION: Recursin es, en ciencias de computacin, una forma de atajar y solventar problemas. De hecho, recursin es una de las ideas centrales de ciencia de computacin. Resolver un problema mediante recursin significa que la solucin depende de las soluciones de pequeas instancias del mismo problema. A continuacin se presenta el desarrollo del tema con relacin a estructura de datos.
Recursin
Contenido
RECURSION ............................................................................................................................................................ 4 Algoritmos recursivos: ....................................................................................................................................... 4 Programacin Recursiva:................................................................................................................................... 5 Ejemplos de subrutinas definidas recursivamente (recursin generativa)..................................... 6 Factorial ................................................................................................................................................................... 6 Fibonacci ................................................................................................................................................................. 8 Mximo comn divisor ...................................................................................................................................... 9 Torres de Hani .................................................................................................................................................. 11 Bsqueda binaria ............................................................................................................................................... 13 Estructuras de datos recursivos (recursin estructural) ...................................................................... 16 Listas enlazadas .................................................................................................................................................. 16 rboles binarios ................................................................................................................................................. 17 Recursin frente a iteracin ........................................................................................................................... 18 Funciones de recursin de cola .................................................................................................................... 19 Recursin directa e indirecta ......................................................................................................................... 20
Recursin
RECURSION
Recursin es, en ciencias de computacin, una forma de atajar y solventar problemas. De hecho, recursin es una de las ideas centrales de ciencia de computacin. Resolver un problema mediante recursin significa que la solucin depende de las soluciones de pequeas instancias del mismo problema. El poder de la recursin evidentemente se fundamenta en la posibilidad de definir un conjunto infinito de objetos con una declaracin finita. Igualmente, un nmero infinito de operaciones computacionales puede describirse con un programa recursivo finito, incluso en el caso de que este programa no contiene repeticiones explcitas." La mayora de los lenguajes de programacin dan soporte a la recursin permitiendo a una funcin llamarse a s misma desde el texto del programa. Los lenguajes imperativos definen las estructuras de loops como while y for que son usadas para realizar tareas repetitivas. Algunos lenguajes de programacin funcionales no definen estructuras de loops sino que posibilitan la recursin llamando cdigo de forma repetitiva. La teora de la computabilidad ha demostrado que estos dos tipos de lenguajes son matemticamente equivalentes, es decir que pueden resolver los mismos tipos de problemas, aunque los lenguajes funcionales carezcan de las tpicas estructuras while y for.
Algoritmos recursivos:
Un mtodo frecuente para simplificar es dividir un problema en problemas ms derivados de menor tamao del mismo tipo. Esto se conoce como dialecting. Cmo tcnica de programacin se denomina divide y vencers y es pieza fundamental para el diseo de muchos algoritmos de importancia, as como parte esencial de la programacin dinmica. Virtualmente todos los lenguajes de programacin modernos permiten la especificacin directa de funciones y subrutinas recursivas. Cuando se llama una funcin de este tipo, el ordenador (para la mayora de lenguajes en casi todas las arquitecturas basadas en unapila (stack) o la implementacin en el lenguaje llevan la cuenta de las distintas instancias de la funcin (en numerosas arquitecturas mediante el uso de un call stack,
Recursin
aunque no de forma exclusiva). A la inversa, toda funcin recursiva puede transformarse en una funcin iterativa usando un stack. La mayora (aunque no todas) las funciones y subrutinas que pueden ser evaluadas por un ordenador, pueden expresarse en trminos de una funcin recursiva (sin tener que utilizar una iteracin pura); a la inversa, cualquier funcin recursiva puede expresarse en trminos de una iteracin pura, dado que la recursin es, de por s, tambin iterativa. Para evaluar una funcin por medio de la recursin, tiene que definirse como una funcin de si misma (ej. el factor n! = n * (n - 1)! , donde 0! se define como 1). Resulta evidente que no todas las evaluaciones de funciones se prestan a un acercamiento recursivo. Por lo general, todas las funciones finitas pueden describirse directamente de forma recursiva; las funciones infinitas (ej. las series de e = 1/1! + 2/2! + 3/3!...) necesitan un criterio extra para detenerse, ej. el nmero de iteraciones, o el nmero de dgitos significativos, en caso contrario una iteracin recursiva resultara en un bucle infinito. A modo de ilustracin: Si se encuentra una palabra desconocida en un libro, el lector puede anotar la pgina actual en un papel y ponerlo en una pila (hasta entonces vaca). El lector consulta la palabra en otro artculo y, de nuevo, descubre otra palabra desconocida, la anota y la pone en la pila, y as sucesivamente. Llega un momento que el lector lee un artculo que donde todas las palabras son conocidas. El lector retorna entonces a la ltima pgina y continua la lectura desde ah, y as hasta que se retira la ltima nota de la pila retornando entonces al libro original. Este modus operandi es recursivo. Algunos lenguajes diseados para programacin lgica y programacin funcional ofrecen la recursin como el nico medio de repeticin directa disponible para el programador. Estos lenguajes suelen conseguir que la recursin de cola sea tan eficiente como la iteracin, permitiendo a los programadores expresar otras estructuras repetitivas (tales como map y for de scheme) en trminos de recursin. La recursin est profundamente anclada en la teora de computacin, con la equivalencia terica de funcin micro recursiva y mquinas de Turing en la cimentacin de ideas sobre la universalidad del ordenador moderno.
Programacin Recursiva:
Crear una subrutina recursiva requiere principalmente la definicin de un "caso base", y entonces definir reglas para subdividir casos ms complejos en el caso base. Para una subrutina recursiva es esencial que con cada llamada recursiva, el problema se reduzca de forma que al final llegue al caso base.
Recursin
Algunos expertos clasifican la recursin como "generativa" o bien "estructural". La distincin se hace segn de donde provengan los datos con los que trabaja la subrutina. Si los datos proceden de una estructura de datos similar a una lista, entonces la subrutina es "estructuralmente recursiva"; en caso contrario, es "generativamente recursiva". Muchos algoritmos populares generan una nueva cantidad de datos a partir de los datos aportados y recurren a partir de ah. HTDP (How To Design Programs), al espaol, "Cmo disear programas", se refiere a esta variante como recursin generativa. Ejemplos de recursin generativa incluyen: mximo comn divisor, quicksort, bsqueda binaria, mergesort, Mtodo de Newton, fractals e integracin adaptiva.
Pseudocdigo (recursivo): funcin input: entero n de forma que n output: [n (n-1) (n-2) 1] factorial: >= 0
end factorial
Recursin
Una relacin recurrente es una ecuacin que relaciona trminos posteriores en la secuencia con trminos previos. Relacin recurrente de un factorial:
Esta funcin factorial tambin puede describirse sin usar recursin hacienda uso de tpicas estructuras de bucle que se encuentran en lenguajes de programacin imperativos: Pseudocdigo (iterativo): funcin input: entero n de factorial forma que n >= es: 0
Recursin
2. begin loop 1. si n es = 0, salir del loop 2. cambiar running_total a (running_total n) 3. decrementar n 4. repetir el loop
3. return running_total
end factorial El lenguaje de programacin scheme es, sin embargo, un lenguaje de programacin funcional y no define estructuras de loops de cualquier tipo. Se basa nicamente en la recursin para ejecutar todo tipo de loops. Dado que scheme es recursivo de cola, se puede definir una subrutina recursiva que implementa la subrutina factorial como un proceso iterativo, es decir, usa espacio constante pero tiempo lineal.
Fibonacci
Otra popular secuencia recursiva es el Nmero de Fibonacci. Los primeros elementos de la secuencia son: 0, 1, 1, 2, 3, 5, 8, 13, 21... Definicin de la funcin:
Recursin
1. si n es = 0, return 0 2. si n es = 1, return 1 3. else, return [ fib(n-1) + fib(n-2) ]
end fib Relacin bn = b1 = 1, b0 = 0 Computando la relacin recurrente para n = 4: b4 = b3 + b2 = b2 + b1 + b1 + b0 = b1 + b0 + 1 + 1 + 0 =1+0+1+1+0 =3 Este algoritmo de Fibonacci es especialmente malo pues cada vez que se ejecuta la funcin, realizar dos llamadas a la funcin a s misma, cada una de las cuales har a la vez dos llamadas ms y as sucesivamente hasta que terminen en 0 o en 1. El ejemplo se denomina "recursin de rbol", y sus requisitos de tiempo crecen de forma exponencial y los de espacio de forma lineal.7 recurrente para bn-1 + Fibonacci: bn-2
Recursin
Pseudocdigo (recursivo): function gcd is: input: entero x, entero y de forma que x >= y y y > 0
end gcd Relacin recursiva del mximo comn denominador, donde divisin entera : expresa el resto de la
Computando la relacin recurrente para x = 27 e y = 9: gcd(27, 9) = gcd(9, 27 % 9) = gcd(9, 0) =9 Computando la relacin recurrente para x = 259 e y = 111: gcd(259, 111) = gcd(111, 259 % 111) = gcd(111, 37) = gcd(37, 0) = 37 Ntese que el algoritmo "recursivo" mostrado arriba es, de hecho, nicamente de cola recursiva, lo que significa que es equivalente a un algoritmo iterativo. En el ejemplo siguiente se muestra el mismo algoritmo usando explcitamente iteracin. No acumula una
10
Recursin
cadena de operaciones deferred, sino que su estado es, ms bien, mantenido completamente en las variables x e y. Su "number of steps grows the as the logarithm of the numbers involved. ",8 al espaol "nmero de pasos crece a medida que lo hace el logaritmo de los nmeros involucrados." Pseudocdigo: funcin gcd es:
2. begin loop 1. if y is zero, exit loop 2. set remainder to the remainder of x/y 3. set x to y 4. set y to remainder 5. repeat loop
3. return x
end gcd El algoritmo iterativo requiere una variable temporal, e incluso supuesto el conocimiento del Algoritmo de Euclides es ms difcil de entender el proceso a simple vista, aunque los dos algoritmos son muy similares en sus pasos.
Torres de Hani
El problema, puesto de forma simple, es el siguiente: Dadas 3 pilas, una con un conjunto de N discos de tamao creciente, determina el mnimo (ptimo) nmero de pasos que
11
Recursin
lleva mover todos los discos desde su posicin inicial a otra pila sin colocar un disco de mayor tamao sobre uno de menor tamao. Definicin de la funcin:
Ejemplos de implementacin: Pseudocdigo (recursivo): function input: integer n, such that n >= 1 hanoi is:
1. if n is 1 then return 1
12
Recursin
end hanoi
Aunque no todas las funciones recursivas tienen una solucin explcita, la secuencia de la Torre de Hanoi puede reducirse a una frmula explcita. Una formula explcita de las Torres de Hanoi: h1 = 1 = 21 - 1 h2 = 3 = 22 - 1 h3 = 7 = 23 - 1 h4 = 15 = 24 - 1 h5 = 31 = 25 - 1 h6 = 63 = 26 - 1 h7 = 127 = 27 - 1 Por lo general: hn = 2n - 1, for all n >= 1
Bsqueda binaria
El algoritmo de bsqueda binaria es un mtodo de bsqueda de un dato en un vector de datos ordenado dividiendo el vector en dos tras cada pasada. El truco es escoger un punto cerca del centro del vector, comparar en ese punto el dato con el dato buscado para responder entonces a una de las siguientes 3 condiciones: se encuentra el dato buscado, el dato en el punto medio es mayor que el valor buscado o el dato en el punto medio es menor que el valor buscado. Se usa recursin en este algoritmo porque tras cada pasada se crea un nuevo vector dividiendo en orginal en dos. La subrutina de bsqueda binaria se llama entonces de forma recursiva, cada vez con un vector de menor tamao. El tamao del vector se ajusta normalmente cambiando el ndice inicial y final. El algoritmo muestra un
13
Recursin
orden logaritmo de crecimiento porque divide esencialmente el dominio del problema en dos tras cada pasada. Ejemplo de implementacin de la bsqueda binaria: /* Call binary_search with proper initial conditions.
Entrada: Los datos se presentan en forma de vector de [[nmero entero|nmeros enteros]] ordenado de forma ascendente, ''toFind'' es el nmero entero a buscar, ''count'' es el nmero total de elementos del vector
*/ int search(int *data, int toFind, int count) { // Start = 0 (ndice inicial) // End = count - 1 (ndice superior) return binary_search(data, toFind, 0, count-1); }
14
Recursin
Entrada: Los datos se presentan en forma de vector de [[nmero entero|nmeros enteros]] ordenado de forma ascendente, ''toFind'' es el nmero entero a buscar, ''start'' es el ndice mnimo del vector, ''end'' es el ndice mximo del vector Salida: posicin del nmero entero ''toFind'' dentro del vector de datos, -1 en caso de bsqueda fallida */ int binary_search(int *data, int toFind, int start, int end) { //Averigua el punto medio. int mid = start + (end - start)/2; //Divisin de enteros
//Condicin para detenerse. if (start > end) return -1; else if (data[mid] == toFind) return mid; else if (data[mid] > toFind) inferior return binary_search(data, toFind, start, mid-1); else //El dato es menor que ''toFind'', se busca en la mitad superior //El dato es mayor que ''toFind'', se busca en la mitad //Encontrado?
15
Recursin
return binary_search(data, toFind, mid+1, end); }
Listas enlazadas
A continuacin se describe una definicin simple del nodo de una lista enlazada. Ntese como se define el nodo por si solo. El siguiente elemento del nodo del struct es un puntero a un nodo de struct. struct node { int n; // algn tipo de datos
16
Recursin
// LIST no es otra cosa que un nodo de ''struct'' *. typedef struct node *LIST; Las subrutinas que operan en la estructura de datos de LIST pueden implementarse de forma natural como una subrutina recursiva porque la estructura de datos sobre la que opera (LIST) es definida de forma recursiva. La subrutina printList definida a continuacin recorre la lista hacia abajo hasta que sta se vaca (NULL), para cada nodo imprime el dato (un nmero entero). En la implementacin en C, la lista permanece inalterada por la subrutina printList. void printList(LIST lst) { if (!isEmpty(lst)) { printf("%d ", lst->n); // imprime el entero seguido por un espacio printList(lst->next); // llamada recursiva } } // caso bsico
rboles binarios
Ms abajo se muestra una definicin simple de un nodo de rbol binario. Al igual que el nodo de listas enlazadas, se define a s misma (de forma recursiva). Hay dos punteros que se refieren a s mismos left (apuntando a l aparte izquierda del subrbol) y right (a la parte derecha del subrbol). struct node { int n; // algn tipo de datos
struct node *left; // puntero al subrbol izquierdo struct node *right; // puntero al subrbol derecho
17
Recursin
};
// TREE no es otra cosa que un nodo '' struct '' typedef struct node *TREE; Las operaciones en el rbol pueden implementarse usando recursin. Ntese que, debido al hecho de que hay dos punteros que se referencian a s mismos (izquierda y derecha), esas operaciones del rbol van a necesitar dos llamadas recursivas. void printTree(TREE t) { if (!isEmpty(t)) { // caso bsico
printTree(t->left); // ir a la izquierda printf("%d ", t->n); // imprimir el entero seguido de un espacio printTree(t->right); // ir a la derecha } } El ejemplo descrito ilustra un rbol binario de orden transversal. Un rbol de bsqueda binaria es un caso especial de rbol binario en el cual los datos de cada rbol estn en orden.
18
Recursin
estos algoritmos pueden implementarse iterativamente con la ayuda de una pila, pero la necesidad del mismo, puede que anule las ventajas de la solucin iterativa. Otra posible razn para la utilizacin de un algoritmo iterativo en lugar de uno recursivo es el hecho de que en los lenguajes de programacin modernos, el espacio de stack disponible para un hilo es, a menudo, mucho menos que el espacio disponible en elmontculo, y los algoritmos recursivos suelen requerir ms espacio de stack que los algoritmos iterativos. Vase, por otro lado, la seccin siguiente que trata el caso especial de la recursin de cola.
19
Recursin
1); } La importancia de recursin de cola es que cuando se realiza una llamada recursiva de cola, la posicin de retorno de la funcin que llama necesita grabarse en el call stack; cuando la funcin recursiva retorna, continuar directamente a partir de la posicin de retorno grabada previamente. Por ello, en compiladores que dan soporte a optimizacin de recursin de cola, este tipo de recursin ahorra espacio y tiempo.
20
Recursin
CONCLUSIONES El poder de la recursin evidentemente se fundamenta en la posibilidad de definir un conjunto infinito de objetos con una declaracin finita. La mayora de los lenguajes de programacin dan soporte a la recursin permitiendo a una funcin llamarse a s misma desde el texto del programa. Crear una subrutina recursiva requiere principalmente la definicin de un "caso base", y entonces definir reglas para subdividir casos ms complejos en el caso base. El algoritmo de bsqueda binaria es un mtodo de bsqueda de un dato en un vector de datos ordenado dividiendo el vector en dos tras cada pasada.
Recursin
RECOMENDACIONES: Investigar acerca recursin en los diferentes lenguajes de programacin. Practicar la recursin en programas de estructura de datos.
Recursin
EGRAFIA http://es.wikipedia.org/wiki/Recursi%C3%B3n_(ciencias_de_computaci%C3%B3n)