Curso-lenguaje-C/fundamentos-programacion/PEC7/README.md
2024-06-27 20:27:23 +02:00

4.7 KiB

PEC 7

Volver a la página principal de "Fundamentos de la Programación"

Índice

20. Recursividad

El concepto de recursividad hace referencia a que un algoritmo se utilice a sí mismo para resolver un problema. En programación, la recursividad se utiliza para resolver problemas que pueden ser descompuestos en problemas más pequeños del mismo tipo. La recursividad es una técnica muy potente, pero también puede ser peligrosa si no se utiliza correctamente, ya que puede llevar a que un programa se ejecute indefinidamente.

20.1. Ejemplo: números naturales

Los número naturales tienen su definición revursiva en matemáticas:

  • 0 ∈ N
  • Si n ∈ N, entonces n+1 ∈ N

El conjunto de números naturales es el mínimo conjunto que cumple estas dos propiedades.

En este caso vemos que para definir qué es un número natural, lo hacemos recursivamente, o sea, a partir de saber que n es recursivo, sabemos que n + 1 también lo es. Con lo cual, lo podemos ver en el siguiente algoritmo:

function isNatural(n: integer): boolean
  var
    result: boolean
  end var

  if n = 0 then
    result := true
  else
    result := isNatural(n - 1)
  end if

  return result

end function
#include <stdbool.h>

bool isNatural(int n) {
  if (n == 0) {
    result = true;
  } else {
    result = isNatural(n - 1);
  }
  return result;
}

En este código vemos un ejemplo de los dos elementos que todo algoritmo recursivo debe tener:

  • Condición de finalización (en este caso cuando n es 0)
  • Regla recursiva (una llamada recursiva con n-1)

En la siguiente figura se puede ver la simulación de lo que pasaría en la memoria cuando se llama isNatural(2).

step 1 - Veremos que cuando se llama isNatural con el valor 2, este queda guardado en una zona de memoria.

| ... | 32 | 33 | 34 | 35  | ... | 65 | 66 | 67 | 68 | ... | 215 | 216 | 217 | 218 | ... |
|-----|----|----|----|-----|-----|----|----|----|----|-----|-----|-----|-----|-----|-----|
| ... |         2          | ... |    |    |    |    | ... |     |     |     |     | ... |

step 2 - Siguiendo con el algoritmo, ya que n no es 0, se hace otra llamada a isNatural con el valor 1. Esta nueva llamada se añade a la pila y queda guardada en otra zona de memoria diferente. Como n todavía no es 0, se vuelve a hacer una llamada a isNatural con el valor 0 y esta nueva llamada también queda añadida a la pila utilizando otra zona de memoria.

| ... | 32 | 33 | 34 | 35  | ... | 65 | 66 | 67 | 68 | ... | 215 | 216 | 217 | 218 | ... |
|-----|----|----|----|-----|-----|----|----|----|----|-----|-----|-----|-----|-----|-----|
| ... |         2          | ... |         1         | ... |     |     |     |     | ... |

step 3 - En este caso, como el parámetro tiene valor 0, se devolverá un true y se finalizará esta llamada.

| ... | 32 | 33 | 34 | 35  | ... | 65 | 66 | 67 | 68 | ... | 215 | 216 | 217 | 218 | ... |
|-----|----|----|----|-----|-----|----|----|----|----|-----|-----|-----|-----|-----|-----|
| ... |         2          | ... |         1         | ... |           0           | ... |

step 4 - Cuando se finaliza la ejecución de una acción o función, toda la memoria ocupada por sus parámetros y variables se elimina y, por lo tanto, ahora solo quedarán las dos llamadas iniciales a la memoria.

| ... | 32 | 33 | 34 | 35  | ... | 65 | 66 | 67 | 68 | ... | 215 | 216 | 217 | 218 | ... |
|-----|----|----|----|-----|-----|----|----|----|----|-----|-----|-----|-----|-----|-----|
| ... |         2          | ... |         1         | ... |     |     |     |     | ... |

step 5 - La segunda llamada devolverá el valor true que ha devuelto la última llamada y, por tanto, finalizará y quedará solo la primera llamada a la memoria. Finalmente esta llamada inicial retornará y también se eliminará de la memoria.

| ... | 32 | 33 | 34 | 35  | ... | 65 | 66 | 67 | 68 | ... | 215 | 216 | 217 | 218 | ... |
|-----|----|----|----|-----|-----|----|----|----|----|-----|-----|-----|-----|-----|-----|
| ... |         2          | ... |    |    |    |    | ... |     |     |     |     | ... |
      |         n          | ... |         n         | ... |           n           | ... |

Lo importante es ver que, aunque sea la misma función, a efectos prácticos es como si se tratara de funciones diferentes y, por tanto, los parámetros y variables que tenga son independientes entre llamadas.

20.2. Ejemplo: factorial

20.3. Ejemplo: Tratamiento secuencial

20.3.1. Funciones auxiliares

20.3.2. Punteros

Volver arriba

Volver a la PEC 6 | Volver al índice principal