Professional Documents
Culture Documents
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
whiley forque 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 whiley for.
ndice
1 Algoritmos recursivos
2 Programacin recursiva
2.1 Ejemplos de subrutinas definidas recursivamente
(recursin generativa)
2.1.1 Factorial
2.1.2 Fibonacci
2.1.3 Mximo comn divisor
2.1.4 Torres de Hani
2.1.5 Bsqueda binaria
2.2 Estructuras de datos recursivo (recursin
estructural)
2.2.1 Listas enlazadas
2.2.2 rboles binarios
2.3 Recursin frente a iteracin
3 Funciones de recursin de cola
4 Orden en el llamamiento de una funcin
4.1 Funcin 1
4.2 Funcin 2 con lneas cambiadas
5 Recursin directa e indirecta
6 Vase tambin
7 Notas y referencias
8 Enlaces externos
https://es.wikipedia.org/wiki/Recursi%C3%B3n_(ciencias_de_computaci%C3%B3n)
1/13
24/9/2015
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 los
lenguajes en casi todas las arquitecturas basadas en una pila (stack) o en la implementacin del lenguaje,
lleva la cuenta de las distintas instancias de la funcin, en numerosas arquitecturas mediante el uso de un
call stack, 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) de 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 mapy forde scheme) en trminos de recursin.
La recursin est profundamente anclada en la teora de computacin, con la equivalencia terica de funcin
microrecursiva 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.
https://es.wikipedia.org/wiki/Recursi%C3%B3n_(ciencias_de_computaci%C3%B3n)
2/13
24/9/2015
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".4
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.5
Pseudocdigo (recursivo):
funcin factorial:
input: entero n de forma que n >= 0
output: [n (n-1) (n-2) 1]
1. if n es 0, return 1
2. else, return [ n factorial(n-1) ]
end factorial
Una relacin recurrente es una ecuacin que relaciona trminos posteriores en la secuencia con trminos
previos.6
Relacin recurrente de un factorial:
https://es.wikipedia.org/wiki/Recursi%C3%B3n_(ciencias_de_computaci%C3%B3n)
3/13
24/9/2015
= 4 * b3
= 4 * 3 * b2
= 4 * 3 * 2 * b1
= 4 * 3 * 2 * 1 * b0
=4*3*2*1*1
=4*3*2*1
=4*3*2
=4*6
= 24
Esta funcin factorial tambin puede describirse sin usar recursin haciendo uso de tpicas estructuras de
bucle que se encuentran en lenguajes de programacin imperativos:
Pseudocdigo (iterativo):
funcin factorial es:
input: entero n de forma que n >= 0
output: [n (n-1) (n-2) 1]
1. crear una variable nueva llamada running_total con un valor = 1
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:
https://es.wikipedia.org/wiki/Recursi%C3%B3n_(ciencias_de_computaci%C3%B3n)
4/13
24/9/2015
Pseudocdigo
function fib is:
input: entero n de forma que n >= 0
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
= 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 si 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
Mximo comn divisor
Otro famosa funcin recursiva es el algoritmo de Euclides, usado para computar el mximo comn divisor
de dos enteros.
Definicin de la funcin:
Pseudocdigo (recursivo):
function gcd is:
input: entero x, entero y de forma que x >= y y y > 0
1. if y is 0, return x
2. else, return [ gcd( y, (remainder of x/y) ) ]
end gcd
https://es.wikipedia.org/wiki/Recursi%C3%B3n_(ciencias_de_computaci%C3%B3n)
5/13
24/9/2015
= gcd(9, 27 % 9)
= gcd(9, 0)
=9
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 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:
input: entero x, entero y de forma que x >= y e y > 0
1. crear una nueva variable llamada remainder
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
https://es.wikipedia.org/wiki/Recursi%C3%B3n_(ciencias_de_computaci%C3%B3n)
6/13
24/9/2015
Para una detallada discusin de la descripcin de este problema, de su historia y de su solucin, consltese
el artculo principal.9 10 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 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:
= 2*hanoi(3) + 1
= 2*(2*hanoi(2) + 1) + 1
= 2*(2*(2*hanoi(1) + 1) + 1) + 1
= 2*(2*(2*1 + 1) + 1) + 1
= 2*(2*(3) + 1) + 1
= 2*(7) + 1
= 15
Ejemplos de implementacin:
Pseudocdigo (recursivo):
function hanoi is:
input: integer n, such that n >= 1
1. if n is 1 then return 1
2. return [2 * [call hanoi(n-1)] + 1]
end hanoi
Aunque no todas las funciones recursivas tienen una solucin explcita, la secuencia de la Torre de Hani
puede reducirse a una frmula explcita.11
https://es.wikipedia.org/wiki/Recursi%C3%B3n_(ciencias_de_computaci%C3%B3n)
7/13
24/9/2015
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 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
Salida:
resultado de la bsqueda binaria
*/
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);
}
/*
Algoritmo de la bsqueda binaria.
Entrada:
Los datos se presentan en forma de vector de [[nmero entero|nmeros enteros]] ordenado de forma ascendent
''toFind'' es el nmero entero a buscar,
''start'' es el ndice mnimo del vector,
''end'' es el ndice mximo del vector
https://es.wikipedia.org/wiki/Recursi%C3%B3n_(ciencias_de_computaci%C3%B3n)
8/13
24/9/2015
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)
//Encontrado?
return mid;
else if (data[mid] > toFind)
//El dato es mayor que ''toFind'', se busca en la mitad inferior
return binary_search(data, toFind, start, mid-1);
else
//El dato es menor que ''toFind'', se busca en la mitad superior
return binary_search(data, toFind, mid+1, end);
}
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
https://es.wikipedia.org/wiki/Recursi%C3%B3n_(ciencias_de_computaci%C3%B3n)
9/13
24/9/2015
(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))
// caso bsico
{
printf("%d ", lst->n); // imprime el entero seguido por un espacio
printList(lst->next); // llamada recursiva
}
}
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
};
// 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. Para un ejemplo similar, vase la funcin de Fibonacci y la explicacin
siguiente.
void printTree(TREE t) {
if (!isEmpty(t)) {
printTree(t->left);
printf("%d ", t->n);
printTree(t->right);
}
}
// caso bsico
// ir a la izquierda
// imprimir el entero seguido de un espacio
// 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.
https://es.wikipedia.org/wiki/Recursi%C3%B3n_(ciencias_de_computaci%C3%B3n)
10/13
24/9/2015
Hay otros tipos de problemas cuyas soluciones son inherentemente recursivas, porque estar al tanto del
estado anterior. Un ejemplo es el rbol transversal; otros incluyen la funcin de Ackermann y el algoritmo
divide y vencers tales como Quicksort. Todos 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 el montculo, 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.
Recursin en aumento:
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.
Funcin 1
void recursiveFunction(int num) {
if (num < 5) {
printf("%d\n", num);
recursiveFunction(num + 1);
}
https://es.wikipedia.org/wiki/Recursi%C3%B3n_(ciencias_de_computaci%C3%B3n)
11/13
24/9/2015
Vase tambin
Recursin primitiva
Programacin funcional
Funcin de Ackermann
Notas y referencias
Esta obra deriva de la traduccin de Recursion (computer science) de Wikipedia en
ingls, concretamente de esta versin (https://en.wikipedia.org/wiki/Recursion_(computer_science)?
oldid=281278816),
publicada
por
sus
editores
(https://en.wikipedia.org/wiki/Recursion_(computer_science)?action=history) bajo la Licencia de
documentacin libre de GNU y la Licencia Creative Commons Atribucin-CompartirIgual 3.0
https://es.wikipedia.org/wiki/Recursi%C3%B3n_(ciencias_de_computaci%C3%B3n)
12/13
24/9/2015
Unported.
1. Epp, Susanna (1995). Discrete Mathematics with Application (2. edicin). p.427.
2. Graham, Ronald; Donald Knuth, Oren Patashnik (1990). Concrete Mathematics (http://www-csfaculty.stanford.edu/~knuth/gkp.html). Captulo 1: Recurrent Problems.
3. Wirth, Niklaus (1976). Algorithms + Data Structures = Programs. Prentice-Hall. p.126.
4. Felleisen, Matthias; Robert Bruce Findler, Matthew Flatt, Shriram Krishnamurthi (2001). How to Design
Programs: An Introduction to Computing and Programming (http://www.htdp.org/2003-09-26/Book/curriculumZ-H-31.html). Cambridge, MASS: MIT Press. p.art V "Generative Recursion".
5. Felleisen, Matthias (2002). Developing Interactive Web Programs. En Jeuring, Johan. Advanced Functional
Programming: 4th International School. Oxford, Reino Unido: Springer. p.108..
6. Epp, Susanna (1995). Discrete Mathematics with Applications. Brooks-Cole Publishing Company. p.424.
7. Abelson, Harold; Gerald Jay Sussman (1996). Structure and Interpretation of Computer Programs
(http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-11.html#%_sec_1.2.2). Seccin 1.2.2.
8. Abelson, Harold; Gerald Jay Sussman (1996). Structure and Interpretation of Computer Programs
(http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-11.html#%_sec_1.2.5). Section 1.2.5.
9. Graham, Ronald; Donald Knuth, Oren Patashnik (1990). Concrete Mathematics (http://www-csfaculty.stanford.edu/~knuth/gkp.html). Chapter 1, Section 1.1: The Tower of Hanoi.
10. Epp, Susanna (1995). Discrete Mathematics with Applications (2nd edicin). pp.427430: The Tower of Hanoi.
11. Epp, Susanna (1995). Discrete Mathematics with Applications (2nd edicin). pp.447448: An Explicit Formula
for the Tower of Hanoi Sequence.
12. Wirth, Niklaus (1976). Algorithms + Data Structures = Programs. Prentice-Hall. p.127.
13. Felleisen, Matthias (2002), Developing Interactive Web Programs, Advanced Functional Programming: 4th
International School, Oxford, UK: Springer, pp.108.
Enlaces externos
Harold Abelson and Gerald Sussman: "Structure and Interpretation Of Computer Programs"
(http://mitpress.mit.edu/sicp/full-text/book/book.html)
IBM
DeveloperWorks:
"Mastering
Recursive
Programming"
(http://www128.ibm.com/developerworks/linux/library/l-recurs.html)
David S. Touretzky: "Common Lisp: A Gentle Introduction to Symbolic Computation"
(http://www.cs.cmu.edu/~dst/LispBook/)
Matthias Felleisen: "How To Design Programs: An Introduction to Computing and Programming"
(http://www.htdp.org/2003-09-26/Book/)
Obtenido
de
title=Recursin_(ciencias_de_computacin)&oldid=82065862
https://es.wikipedia.org/w/index.php?
https://es.wikipedia.org/wiki/Recursi%C3%B3n_(ciencias_de_computaci%C3%B3n)
13/13