¿Cuáles son los problemas del mundo real donde un enfoque recursivo es la solución natural además de la búsqueda en profundidad (DFS)?
(No considero la Torre de Hanoi , el número de Fibonacci o los problemas factoriales del mundo real. Son un poco inventados en mi mente).
Respuestas:
Hay muchos ejemplos matemáticos aquí, pero querías un ejemplo del mundo real , así que con un poco de pensamiento, esto es posiblemente lo mejor que puedo ofrecer:
Encuentra a una persona que ha contraído una determinada infección contagiosa, que no es mortal, y se cura por sí sola rápidamente (tipo A), excepto una de cada 5 personas (las llamaremos tipo B) que se infectan permanentemente y no muestran síntomas y simplemente actúa como esparcidor.
Esto crea olas de estragos bastante molestas cuando el tipo B infecta a una multitud de tipo A.
Su tarea es localizar a todos los tipos B e inmunizarlos para detener la columna vertebral de la enfermedad. Desafortunadamente, no se puede administrar una cura a nivel nacional para todos, porque las personas que son tipo A también son mortalmente alérgicas a la cura que funciona para el tipo B.
La forma en que haría esto sería el descubrimiento social, dada una persona infectada (Tipo A), elegir todos sus contactos en la última semana, marcando cada contacto en un montón. Cuando pruebe que una persona está infectada, agréguela a la cola de "seguimiento". Cuando una persona es del tipo B, agréguela al "seguimiento" en la parte superior (porque desea detener esto rápido).
Después de procesar a una persona determinada, seleccione a la persona del frente de la cola y aplique la inmunización si es necesario. Consiga que todos sus contactos no hayan sido visitados anteriormente y luego pruebe para ver si están infectados.
Repita hasta que la cola de personas infectadas se convierta en 0 y luego espere otro brote.
(De acuerdo, esto es un poco iterativo, pero es una forma iterativa de resolver un problema recursivo, en este caso, el primer recorrido en amplitud de una base de población tratando de descubrir posibles caminos a los problemas y, además, las soluciones iterativas suelen ser más rápidas y efectivas , y elimino compulsivamente la recursividad en todas partes tanto que se vuelve instintivo ... ¡maldita sea!)
fuente
Un ejemplo real de recursividad
fuente
¿Qué tal cualquier cosa que involucre una estructura de directorios en el sistema de archivos? Buscar archivos de forma recursiva, eliminar archivos, crear directorios, etc.
Aquí hay una implementación de Java que imprime de forma recursiva el contenido de un directorio y sus subdirectorios.
fuente
Clasificación rápida , clasificación combinada y la mayoría de las demás clasificaciones N-log N.
fuente
El ejemplo de Matt Dillard es bueno. De manera más general, cualquier caminata sobre un árbol puede manejarse por recursividad muy fácilmente. Por ejemplo, compilar árboles de análisis, caminar sobre XML o HTML, etc.
fuente
La recursividad se usa a menudo en implementaciones del algoritmo Backtracking . Para una aplicación del "mundo real" de esto, ¿qué tal un solucionador de Sudoku ?
fuente
La recursividad es apropiada siempre que un problema se pueda resolver dividiéndolo en subproblemas, que pueden usar el mismo algoritmo para resolverlos. Los algoritmos en árboles y listas ordenadas son un ajuste natural. Muchos problemas de geometría computacional (y juegos 3D) se pueden resolver de forma recursiva utilizando árboles de partición de espacio binario (BSP), subdivisiones gruesas u otras formas de dividir el mundo en subpartes.
La recursividad también es apropiada cuando se intenta garantizar la exactitud de un algoritmo. Dada una función que toma entradas inmutables y devuelve un resultado que es una combinación de llamadas recursivas y no recursivas en las entradas, generalmente es fácil probar que la función es correcta (o no) mediante inducción matemática. A menudo es difícil hacer esto con una función iterativa o con entradas que pueden mutar. Esto puede ser útil cuando se trata de cálculos financieros y otras aplicaciones donde la corrección es muy importante.
fuente
Seguramente muchos compiladores usan la recursividad en gran medida. Los lenguajes de computadora son inherentemente recursivos en sí mismos (es decir, puede incrustar declaraciones 'if' dentro de otras declaraciones 'if', etc.).
fuente
Desactivación / configuración de solo lectura para todos los controles secundarios en un control de contenedor. Necesitaba hacer esto porque algunos de los controles secundarios eran contenedores.
fuente
Famoso ciclo de evaluación / aplicación de SICP
(fuente: mit.edu )
Aquí está la definición de eval:
Aquí está la definición de aplicar:
Aquí está la definición de secuencia de evaluación:
eval
->apply
->eval-sequence
->eval
fuente
La recursividad se usa en cosas como árboles BSP para la detección de colisiones en el desarrollo de juegos (y otras áreas similares).
fuente
La gente suele clasificar pilas de documentos mediante un método recursivo. Por ejemplo, imagine que está clasificando 100 documentos con nombres. Primero coloque los documentos en pilas por la primera letra, luego clasifique cada pila.
La búsqueda de palabras en el diccionario a menudo se realiza mediante una técnica de búsqueda binaria, que es recursiva.
En las organizaciones, los jefes a menudo dan órdenes a los jefes de departamento, quienes a su vez dan órdenes a los gerentes, etc.
fuente
Requisito del mundo real que obtuve recientemente:
Requisito A: implemente esta función después de comprender a fondo el requisito A.
fuente
Los analizadores y compiladores pueden escribirse en un método de descenso recursivo. No es la mejor manera de hacerlo, ya que herramientas como lex / yacc generan analizadores sintácticos más rápidos y eficientes, pero conceptualmente simples y fáciles de implementar, por lo que siguen siendo comunes.
fuente
La recursividad se aplica a problemas (situaciones) en las que puede dividirla (reducirla) en partes más pequeñas, y cada parte se ve similar al problema original.
Buenos ejemplos de dónde están las cosas que contienen partes más pequeñas similares a sí mismas:
La recursividad es una técnica para seguir dividiendo el problema en trozos cada vez más pequeños, hasta que uno de esos trozos se vuelve lo suficientemente pequeño como para ser un pedazo de pastel. Por supuesto, después de dividirlos, debe "unir" los resultados en el orden correcto para formar una solución total de su problema original.
Algunos algoritmos de clasificación recursiva, algoritmos de caminata por árboles, algoritmos de mapa / reducción, divide y vencerás son todos ejemplos de esta técnica.
En programación de computadoras, la mayoría de los lenguajes de devolución de llamadas basados en pilas ya tienen las capacidades integradas para la recursividad: es decir,
fuente
Tengo un sistema que usa recursividad de cola pura en algunos lugares para simular una máquina de estado.
fuente
Algunos buenos ejemplos de recursividad se encuentran en lenguajes de programación funcionales . En los lenguajes de programación funcional ( Erlang , Haskell , ML / OCaml / F # , etc.), es muy común que cualquier procesamiento de listas utilice la recursividad.
Cuando se trata de listas en lenguajes típicos imperativos de estilo OOP, es muy común ver listas implementadas como listas enlazadas ([item1 -> item2 -> item3 -> item4]). Sin embargo, en algunos lenguajes de programación funcional, encontrará que las listas en sí mismas se implementan de forma recursiva, donde la "cabeza" de la lista apunta al primer elemento de la lista y la "cola" apunta a una lista que contiene el resto de los elementos ( [elemento1 -> [elemento2 -> [elemento3 -> [elemento4 -> []]]]]). Es bastante creativo en mi opinión.
Este manejo de listas, cuando se combina con la coincidencia de patrones, es MUY poderoso. Digamos que quiero sumar una lista de números:
Esto esencialmente dice "si fuimos llamados con una lista vacía, devuelve 0" (lo que nos permite romper la recursividad), de lo contrario devuelve el valor de head + el valor de Sum llamado con los elementos restantes (de ahí, nuestra recursividad).
Por ejemplo, podría tener una lista de URL , creo que dividir todas las URL a las que enlaza cada URL y luego reducir la cantidad total de enlaces hacia / desde todas las URL para generar "valores" para una página (un enfoque que Google toma con PageRank y que puede encontrar definido en el documento MapReduce original ). También puede hacer esto para generar recuentos de palabras en un documento. Y muchas, muchas, muchas otras cosas también.
Puede extender este patrón funcional a cualquier tipo de código MapReduce donde puede tomar una lista de algo, transformarlo y devolver algo más (ya sea otra lista o algún comando zip en la lista).
fuente
XML, o atravesar cualquier cosa que sea un árbol. Aunque, para ser honesto, casi nunca uso la recursividad en mi trabajo.
fuente
Bucles de retroalimentación en una organización jerárquica.
El jefe superior les dice a los altos ejecutivos que recopilen comentarios de todos en la empresa.
Cada ejecutivo reúne a sus subordinados directos y les dice que recopilen comentarios de sus subordinados directos.
Y en la línea.
Las personas que no tienen subordinados directos (los nodos hoja del árbol) dan su opinión.
La retroalimentación viaja por el árbol y cada gerente agrega su propia retroalimentación.
Eventualmente, todos los comentarios regresan al jefe superior.
Esta es la solución natural porque el método recursivo permite filtrar en cada nivel: la recopilación de duplicados y la eliminación de comentarios ofensivos. El jefe superior podría enviar un correo electrónico global y hacer que cada empleado le informe directamente de sus comentarios, pero existen los problemas de "no puedes manejar la verdad" y "estás despedido", por lo que la recursividad funciona mejor aquí.
fuente
Suponga que está creando un CMS para un sitio web, donde sus páginas están en una estructura de árbol, con la raíz como la página de inicio.
Suponga también que su {usuario | cliente | cliente | jefe} solicita que coloque una ruta de navegación en cada página para mostrar dónde se encuentra en el árbol.
Para cualquier página n dada, es posible que desee caminar hasta el padre de n, y su padre, y así sucesivamente, de forma recursiva para construir una lista de nodos hasta la raíz del árbol de la página.
Por supuesto, está presionando la base de datos varias veces por página en ese ejemplo, por lo que es posible que desee usar algunos alias de SQL donde busque page-table como a, y page-table nuevamente como b, y unir a.id con b.parent para que la base de datos realice las uniones recursivas. Ha pasado un tiempo, por lo que mi sintaxis probablemente no sea útil.
Por otra parte, es posible que solo desee calcular esto una vez y almacenarlo con el registro de página, actualizándolo solo si mueve la página. Probablemente sería más eficiente.
De todos modos, ese es mi $ .02
fuente
Tiene un árbol de organización que tiene N niveles de profundidad. Varios de los nodos están marcados y desea expandirlos solo a los nodos que se han verificado.
Esto es algo que realmente codifiqué. Es agradable y fácil con la recursividad.
fuente
En mi trabajo tenemos un sistema con una estructura de datos genérica que se puede describir como un árbol. Eso significa que la recursividad es una técnica muy eficaz para trabajar con los datos.
Resolverlo sin recursividad requeriría mucho código innecesario. El problema con la recursividad es que no es fácil seguir lo que sucede. Realmente tienes que concentrarte al seguir el flujo de ejecución. Pero cuando funciona, el código es elegante y eficaz.
fuente
Cálculos para finanzas / física, como promedios compuestos.
fuente
fuente
Analizar un árbol de controles en Windows Forms o WebForms (.NET Windows Forms / ASP.NET ).
fuente
El mejor ejemplo que conozco es el ordenamiento rápido , es mucho más simple con la recursividad. Echa un vistazo a:
shop.oreilly.com/product/9780596510046.do
www.amazon.com/Beautiful-Code-Leading-Programmers-Practice/dp/0596510047
(Haga clic en el primer subtítulo debajo del capítulo 3: "El código más hermoso que he escrito").
fuente
Las empresas de telefonía y cable mantienen un modelo de su topología de cableado, que de hecho es una gran red o gráfico. La recursividad es una forma de recorrer este modelo cuando desea encontrar todos los elementos principales o secundarios.
Dado que la recursividad es costosa desde la perspectiva del procesamiento y la memoria, este paso normalmente solo se realiza cuando se cambia la topología y el resultado se almacena en un formato de lista preordenado modificado.
fuente
El razonamiento inductivo, el proceso de formación de conceptos, es de naturaleza recursiva. Tu cerebro lo hace todo el tiempo, en el mundo real.
fuente
Lo mismo ocurre con el comentario sobre los compiladores. Los nodos del árbol de sintaxis abstracta se prestan naturalmente a la recursividad. Todas las estructuras de datos recursivas (listas vinculadas, árboles, gráficos, etc.) también se manejan más fácilmente con la recursividad. Creo que la mayoría de nosotros no usamos mucho la recursividad una vez que salimos de la escuela debido a los tipos de problemas del mundo real, pero es bueno tenerlo en cuenta como una opción.
fuente
La multiplicación de números naturales es un ejemplo real de recursividad:
fuente