Capitulo 4: Algoritmos recursivos
Conceptos básicos de recursividad Se dice que un método es recursivo si contiene llamadas o  invocaciones a sí mismo. Un método recursivo tendría este aspecto: …  metodoRecursivo (…){ …… metodoRecursivo (…); …… } Esto implica que una llamada al método recursivo puede generar una o  más invocaciones al mismo método, que a su vez genera otras  invocaciones, y así sucesivamente.
Condiciones que debe cumplir todo método recursivo Siempre hay que asegurar que existe una condición de salida, es decir,  si se cumple esa condición, estaremos en el caso base, donde no se  producen llamadas recursivas. Ejemplo para un algoritmo recursivo del factorial: Además, es conveniente comprobar que: Entre el caso base y los casos no base, se han cubierto todos los estados posibles. Cada llamada, en el caso no base, conduce a problemas cada vez más pequeños que necesariamente terminarán en el caso base. return n*factorial(n-1) n>1 return 1 n=1 (caso base) Solución Casos
Programa: static int factorial (int n){ if (n>1) return factorial (n-1)*n; else return 1; }
Cuándo debe utilizarse la recursividad   Ya que la solución recursiva tiene un coste de tiempo y memoria mayor  que la iterativa. Es decir, los programas recursivos en general son  menos eficientes. Podríamos utilizar los siguientes consejos: Los algoritmos que por naturaleza son recursivos, y donde la solución iterativa es complicada y debe manejarse explícitamente una pila para enumerar las llamadas recursivas, deben resolverse por métodos recursivos. Cuando haya una solución obvia por iteración al problema, debe evitarse la recursividad. A continuación, se verá un ejemplo donde no debe utilizarse la  recursividad, aunque la solución recursiva es muy sencilla y natural  pero extremadamente ineficiente. La solución iterativa es mucho más  eficiente aunque no tan trivial.
Calcular el término n de la sucesión Fibonacci. Fibonacci (n) = n, si n= 0, o n=1; Fibonacci (n) = Fibonacci (n-1) + Fibonacci (n-2), si n>1 Programa: Public int fib (int n){ if (n>1) return fib(n-1) + fib(n-2); else return n; } Es ineficiente comparado con el iterativo ya que cuando un número n  sea mayor que 1 invocará a la llamada dos veces lo cual implica mayor  tiempo de ejecución y más memoria.
Algoritmos de backtraking El backtraking o “vuelta atrás” es una técnica algorítmica de resolución  general de problemas mediante una búsqueda sistemática de  soluciones. Se descompone la tarea a realizar en tareas parciales de posibles  soluciones, y estas tareas parciales a su ves se descompondrán en  más tareas, en caso de que una tarea no conduzca a una solución se  tendrá que hacer vuelta atrás guardando los puntos de elección para  poder volver a ellos cuando no se alcance una solución.

Algoritmos recursivos

  • 1.
  • 2.
    Conceptos básicos derecursividad Se dice que un método es recursivo si contiene llamadas o invocaciones a sí mismo. Un método recursivo tendría este aspecto: … metodoRecursivo (…){ …… metodoRecursivo (…); …… } Esto implica que una llamada al método recursivo puede generar una o más invocaciones al mismo método, que a su vez genera otras invocaciones, y así sucesivamente.
  • 3.
    Condiciones que debecumplir todo método recursivo Siempre hay que asegurar que existe una condición de salida, es decir, si se cumple esa condición, estaremos en el caso base, donde no se producen llamadas recursivas. Ejemplo para un algoritmo recursivo del factorial: Además, es conveniente comprobar que: Entre el caso base y los casos no base, se han cubierto todos los estados posibles. Cada llamada, en el caso no base, conduce a problemas cada vez más pequeños que necesariamente terminarán en el caso base. return n*factorial(n-1) n>1 return 1 n=1 (caso base) Solución Casos
  • 4.
    Programa: static intfactorial (int n){ if (n>1) return factorial (n-1)*n; else return 1; }
  • 5.
    Cuándo debe utilizarsela recursividad Ya que la solución recursiva tiene un coste de tiempo y memoria mayor que la iterativa. Es decir, los programas recursivos en general son menos eficientes. Podríamos utilizar los siguientes consejos: Los algoritmos que por naturaleza son recursivos, y donde la solución iterativa es complicada y debe manejarse explícitamente una pila para enumerar las llamadas recursivas, deben resolverse por métodos recursivos. Cuando haya una solución obvia por iteración al problema, debe evitarse la recursividad. A continuación, se verá un ejemplo donde no debe utilizarse la recursividad, aunque la solución recursiva es muy sencilla y natural pero extremadamente ineficiente. La solución iterativa es mucho más eficiente aunque no tan trivial.
  • 6.
    Calcular el términon de la sucesión Fibonacci. Fibonacci (n) = n, si n= 0, o n=1; Fibonacci (n) = Fibonacci (n-1) + Fibonacci (n-2), si n>1 Programa: Public int fib (int n){ if (n>1) return fib(n-1) + fib(n-2); else return n; } Es ineficiente comparado con el iterativo ya que cuando un número n sea mayor que 1 invocará a la llamada dos veces lo cual implica mayor tiempo de ejecución y más memoria.
  • 7.
    Algoritmos de backtrakingEl backtraking o “vuelta atrás” es una técnica algorítmica de resolución general de problemas mediante una búsqueda sistemática de soluciones. Se descompone la tarea a realizar en tareas parciales de posibles soluciones, y estas tareas parciales a su ves se descompondrán en más tareas, en caso de que una tarea no conduzca a una solución se tendrá que hacer vuelta atrás guardando los puntos de elección para poder volver a ellos cuando no se alcance una solución.