Este problema se centra principalmente en el algoritmo, quizás algo abstracto y más académico.
El ejemplo es ofrecer un pensamiento, quiero una forma genérica, por lo que el ejemplo solo se usa para hacernos más claros sobre sus pensamientos.
En términos generales, un bucle se puede convertir en recursivo.
p.ej:
for(int i=1;i<=100;++i){sum+=i;}
Y su recursivo relacionado es:
int GetTotal(int number)
{
if (number==1) return 1; //The end number
return number+GetTotal(number-1); //The inner recursive
}
Y finalmente para simplificar esto, se necesita un recursivo de cola:
int GetTotal (int number, int sum)
{
if(number==1) return sum;
return GetTotal(number-1,sum+number);
}
Sin embargo, la mayoría de los casos no son tan fáciles de responder y analizar. Lo que quiero saber es:
1) ¿Podemos obtener una "forma común general" para convertir un bucle (por / mientras ......) en un recursivo? ¿Y a qué tipo de cosas debemos prestar atención mientras hacemos la conversión? Sería mejor escribir información detallada con algunas muestras y sus teorías persuasivas, así como el proceso de conversión.
2) "Recursivo" tiene dos formas: Linely recursive y Tail-Recursive. Entonces, ¿cuál es mejor para convertir? ¿Qué "regla" debemos dominar?
3) A veces necesitamos mantener el "historial" de recursivo, esto se puede hacer fácilmente en una declaración de bucle:
p.ej:
List<string> history = new List<string>();
int sum=0;
for (int i=1;i<=100;++i)
{
if(i==1) history.Add(i.ToString()+"'s result is:1.");
else
{
StringBuilder sub = new StringBuilder();
for(int j=1;j<=i;++j)
{
if(j==i) sbu.Append(j.ToString());
else
{
sub.Append(j.ToString()+"+");
}
}
sum +=i;
sbu.Append("'s result is:"+sum+Environment.NewLine);
}
}
El resultado a continuación es:
El resultado de 1 es 1.
El resultado de 1 + 2 es 3.
El resultado de 1 + 2 + 3 es 6 …………
Sin embargo, creo que es difícil mantener el historial de forma recursiva, porque un algoritmo recursivo se enfoca en obtener el último resultado y hacer una devolución de llamada. Entonces, todo esto se hace a través de la pila mantenida por el lenguaje de programación que asigna memoria en forma de pila automáticamente. ¿ Y cómo podemos "manualmente" sacar cada uno de los "valores de la pila" y devolver múltiples valores a través de un algoritmo recursivo?
¿Y qué hay de "de un algoritmo recursivo a un bucle"? ¿Se pueden convertir entre sí? (Creo que debería hacerse teóricamente, pero quiero cosas más precisas para probar mis pensamientos) .
fuente
Respuestas:
En realidad, primero debes descomponer la función:
Un bucle tiene algunas partes:
el encabezado y el procesamiento antes del bucle. Puede declarar algunas variables nuevas.
la condición, cuándo detener el ciclo.
El cuerpo del bucle real. Cambia algunas de las variables del encabezado y / o los parámetros pasados.
la cola; qué sucede después del bucle y devuelve el resultado.
O para escribirlo:
Usar estos bloques para hacer una llamada recursiva es bastante sencillo:
Et voilà; Una versión recursiva de cola de cualquier bucle.
break
s ycontinue
s en el cuerpo del bucle aún tendrán que ser reemplazadosreturn tail
y regresarfoo_recursion(params, modified_header_vars)
según sea necesario, pero eso es bastante simple.Ir hacia el otro lado es más complicado; en parte porque puede haber múltiples llamadas recursivas. Esto significa que cada vez que hacemos estallar un marco de pila puede haber múltiples lugares donde necesitamos continuar. También puede haber variables que necesitamos guardar en la llamada recursiva y los parámetros originales de la llamada.
Podemos usar un interruptor para evitar eso:
fuente
Siguiendo con la respuesta de @ratchet freak, creé este ejemplo de cómo la función Fibonacci se puede reescribir en un ciclo while en Java. Tenga en cuenta que hay una forma mucho más simple (y eficiente) de reescribir el Fibonacci con un ciclo while.
fuente