¿Es correcto decir que dondequiera que se use la recursividad se for
podría usar un bucle? Y si la recursividad suele ser más lenta, ¿cuál es la razón técnica para usarla en for
iteración de bucle?
Y si siempre es posible convertir una recursividad en un for
bucle, ¿existe una regla general para hacerlo?
recursion
vsiteration
?iteration = for loop
Yo creo que.Respuestas:
La recursividad suele ser mucho más lenta porque todas las llamadas a funciones deben almacenarse en una pila para permitir el retorno a las funciones del llamador. En muchos casos, la memoria debe asignarse y copiarse para implementar el aislamiento del alcance.
Algunas optimizaciones, como la optimización de la llamada de cola , hacen que las recursiones sean más rápidas, pero no siempre son posibles y no se implementan en todos los idiomas.
Las principales razones para utilizar la recursividad son
Por supuesto, cada recursividad se puede modelar como una especie de bucle: eso es lo que finalmente hará la CPU. Y la recursividad en sí, más directamente, significa poner las llamadas de función y los ámbitos en una pila. Pero cambiar su algoritmo recursivo a uno de bucle podría requerir mucho trabajo y hacer que su código sea menos fácil de mantener: como para cada optimización, solo debe intentarse cuando algún perfil o evidencia muestre que es necesario.
fuente
f(n)
que devuelva el n-ésimo número de Fibonacci .Sí, porque la recursividad en la mayoría de las CPU se modela con bucles y una estructura de datos de pila.
No es "normalmente más lento": es la recursividad que se aplica incorrectamente lo que es más lento. Además de eso, los compiladores modernos son buenos para convertir algunas recursiones en bucles sin siquiera preguntar.
Escriba programas iterativos para algoritmos que se comprendan mejor cuando se explican de manera iterativa; escribir programas recursivos para algoritmos que se expliquen mejor de forma recursiva.
Por ejemplo, la búsqueda de árboles binarios, la ejecución de ordenación rápida y el análisis de expresiones en muchos lenguajes de programación a menudo se explica de forma recursiva. Estos también se codifican mejor de forma recursiva. Por otro lado, calcular factoriales y calcular números de Fibonacci es mucho más fácil de explicar en términos de iteraciones. Usar la recursividad para ellos es como aplastar moscas con un mazo: no es una buena idea, incluso cuando el mazo hace un buen trabajo + .
+ Tomé prestada la analogía del mazo de "Disciplina de programación" de Dijkstra.
fuente
Pregunta:
Responder :
Porque en algunos algoritmos es difícil resolverlo de forma iterativa. Intente resolver la búsqueda en profundidad de forma recursiva e iterativa. Obtendrá la idea de que es simplemente difícil resolver DFS con iteración.
Otra cosa buena para probar: intente escribir Merge sort iterativamente. Te llevará bastante tiempo.
Pregunta:
Responder :
Si. Este hilo tiene una muy buena respuesta para esto.
Pregunta:
Responder :
Créeme. Intente escribir su propia versión para resolver la búsqueda en profundidad de forma iterativa. Notarás que algunos problemas son más fáciles de resolver de forma recursiva.
Sugerencia: la recursividad es buena cuando se está resolviendo un problema que se puede resolver mediante la técnica de dividir y conquistar .
fuente
Además de ser más lenta, la recursividad también puede resultar en errores de desbordamiento de pila dependiendo de qué tan profundo sea.
fuente
Para escribir un método equivalente usando iteración, debemos usar explícitamente una pila. El hecho de que la versión iterativa requiera una pila para su solución indica que el problema es lo suficientemente difícil como para que pueda beneficiarse de la recursividad. Como regla general, la recursividad es más adecuada para problemas que no se pueden resolver con una cantidad fija de memoria y, en consecuencia, requieren una pila cuando se resuelven iterativamente. Dicho esto, la recursividad y la iteración pueden mostrar el mismo resultado mientras siguen un patrón diferente. Decidir qué método funciona mejor es caso por caso y la mejor práctica es elegir en función del patrón que sigue el problema.
Por ejemplo, para encontrar el n-ésimo número triangular de una secuencia triangular: 1 3 6 10 15… Un programa que usa un algoritmo iterativo para encontrar el n-ésimo número triangular:
Usando un algoritmo iterativo:
Usando un algoritmo recursivo:
fuente
La mayoría de las respuestas parecen asumir que
iterative
=for loop
. Si su bucle for no tiene restricciones ( a la C, puede hacer lo que quiera con su contador de bucles), entonces eso es correcto. Si se trata de un verdaderofor
bucle (digamos como en Python o la mayoría de los lenguajes funcionales donde no se puede modificar manualmente el contador del bucle), entonces es no correcta.Todas las funciones (computables) se pueden implementar tanto de forma recursiva como mediante
while
bucles (o saltos condicionales, que son básicamente lo mismo). Si realmente se restringefor loops
, solo obtendrá un subconjunto de esas funciones (las primitivas recursivas, si sus operaciones elementales son razonables). Por supuesto, es un subconjunto bastante grande que contiene todas las funciones que es probable que encuentre en la práctica.Lo que es mucho más importante es que muchas funciones son muy fáciles de implementar de forma recursiva y terriblemente difíciles de implementar de forma iterativa (la gestión manual de la pila de llamadas no cuenta).
fuente
Sí, como dicho por Thanakron Tandavas ,
Por ejemplo: Towers of Hanoi
fuente
Creo recordar que mi profesor de ciencias de la computación dijo en su día que todos los problemas que tienen soluciones recursivas también tienen soluciones iterativas. Él dice que una solución recursiva suele ser más lenta, pero se usan con frecuencia cuando son más fáciles de razonar y codificar que las soluciones iterativas.
Sin embargo, en el caso de soluciones recursivas más avanzadas, no creo que siempre pueda implementarlas usando un
for
bucle simple .fuente
recursividad + memorización podría conducir a una solución más eficiente en comparación con un enfoque iterativo puro, por ejemplo, verifique esto: http://jsperf.com/fibonacci-memoized-vs-iterative-for-large-n
fuente
Respuesta corta: la compensación es que la recursividad es más rápida y los bucles for ocupan menos memoria en casi todos los casos. Sin embargo, generalmente hay formas de cambiar el bucle for o la recursividad para que se ejecute más rápido
fuente