Complejidad recursiva.

5 respuestas [Último envío]
Usuario Desconectado. Visto por última vez 1 año 10 semanas. Desconectado
Integró: 19/06/2009
Puntos: 6

Hola a todos. Dando vueltas por internet he encontrado este foro, muy interesante, en el cual espero que me puedan resolver un par de dudas que tengo con respecto a la complejidad temporal de los algoritmos recursivos. Aquí dejo la primer duda que tengo:

Normal 0 21 false false false MicrosoftInternetExplorer4

int g (int x) {                

     // pre: x >=0 

             if (x = = 0)

                         return(1);

            else  

                         return( f (g(x-1) * 3 )); }        //    pertenece a O(k)


Mi duda es cómo calculo el tiempo de f(g(x-1)*3.

La multiplicación por 3 es una constante O(1), mientras que f pertenece a O(k), pero para llamarla, invoca a la recursión.

Me he perdido bastante así que gracias de antemano a todos.

 

Su voto: Nada Promedio: 4 (1 vote)
Imagen de manu
Usuario Desconectado. Visto por última vez 24 semanas 6 días. Desconectado
Integró: 19/11/2007
Puntos: 52
Tail Recursion

Hay una capacidad en los compiladores modernos llamada Tail Recursion. Consiste en que si la última llamada propicia la recursión, esta puede ser generada de manera casi iterativa, creo que con un poco más de memoria pero igual de rápida.

Ejemplo:

 

int factorial(int number) {
if(number == 0) {
return 1;
}
factorial_i(number, 1);
}

int factorial_i(int currentNumber, int sum) {
if(currentNumber == 1) {
return sum;
} else {
return factorial_i(currentNumber - 1, sum*currentNumber);
}
}

Por cierto, ¿ como coloco un bloque de código?

 

Manuel A. Bellido OViedo,
Student of the School of Computer Science,
San Pablo Catholic University,Arequipa, Peru
http://www.mbellido.info/,

Imagen de ivan_sipi
Usuario Desconectado. Visto por última vez 6 días 17 horas. Desconectado
Integró: 15/11/2006
Puntos: 64
Problema con Lenguajes Imperativos

Aún cuando la recursión por la cola significa una mejora cuando se traducen funciones recursivas en un compilador, en los lenguajes imperativos queda un problema. Cada vez que se hace una llamada recursiva queda pendiente el contexto de control a la espera del valor a retornar. Por lo que de todas maneras el valor retornado al final debe volver a recorrer toda la pila de llamadas para que el valor sea devuelto por la llamada original a "factorial" en tu ejemplo. 

Una diferencia se ve en Scheme por ejemplo:

(define (factorial n p)

     (if (= n 1)

            p

            (factorial (- n 1) (* p n))

     )

)

En este caso, el interprete empieza a evaluar una expresion como (factorial 5 1) por ejemplo, pero la diferencia es que cuando llega al final de la recursión (cuando tiene que devolver p), directamente devuelve el valor, y eso se debe a que el interprete de Scheme se da cuenta que la función usa recursión por la cola, por lo que el contexto de control es vacío. Bueno, esto solo es posible dado que en Scheme todo se reduce a un valor del lenguaje y si ese valor ya se calculó, no hay nada más que hacer.

Saludos.

Iván Sipirán Mendoza
Estudiante de Doctorado en Ciencias de la Computación
Universidad de Chile

Imagen de manu
Usuario Desconectado. Visto por última vez 24 semanas 6 días. Desconectado
Integró: 19/11/2007
Puntos: 52
Creo que eso no es tail recursion

Bueno, cuando pones :

 

  (factorial (- n 1) (* p n))

lo último que realiza el código no es la llamada a función, sino que tiene que esperar la respuesta para realizar el producto. Tail recursion sería : 

 

Factorial( -n 1, p)

 

En ese caso lo único que hace es llamar a la función(adentro ya podrías multiplicar p), condición necesaria para tail recursion.

Manuel A. Bellido OViedo,
Student of the School of Computer Science,
San Pablo Catholic University,Arequipa, Peru
http://www.mbellido.info/,

Imagen de ivan_sipi
Usuario Desconectado. Visto por última vez 6 días 17 horas. Desconectado
Integró: 15/11/2006
Puntos: 64
Correción

Es que Scheme usa notación infija de invocación a funciones(osea (- n 1) es el primer parámetro de la función y (* n p) es el segundo parámetro, obviamente la primera expresión "factorial" es la llamada a la función recursivamente) y y la evaluación de expresiones es estricta, por eso los argumentos se evalúan antes de invocar a la función :).

De hecho es la versión Scheme del mismo procedimiento que colocaste tú, solo que mi intención era diferenciar lo que sucedía con los contextos de control durante las llamadas recursivas, que en este caso se desestiman cuando el valor final es devuelto :).

 

Saludos.

Iván Sipirán Mendoza
Estudiante de Doctorado en Ciencias de la Computación
Universidad de Chile

Imagen de manu
Usuario Desconectado. Visto por última vez 24 semanas 6 días. Desconectado
Integró: 19/11/2007
Puntos: 52
Cierto!

Si me acabo de dar cuenta, justo en el siguiente link hay un ejemplo con la misma función y explica como funciona esto del Tail recursion:

 

http://en.wikipedia.org/wiki/Tail_recursion

Manuel A. Bellido OViedo,
Student of the School of Computer Science,
San Pablo Catholic University,Arequipa, Peru
http://www.mbellido.info/,

Distribuir contenido