2.5.4 ¿Cuándo usar la Recursión y cuándo la Iteración?


Tomado del tutorial por ©Collin Allen y ManeeshDhagat, April 1997.
Traducción del inglés: Reinaldo Togores, 1999.

Hay muchos problemas para los cuales la recursiónresulta natural y para los cuales la iteración resulta extremadamentedifícil. Esto sucede usualmente cuando se tienen en cuenta objetos conuna estructura compleja de listas anidadas. Por ejemplo, consideremos estaexpresión matemática en formato LISP:

(setq math-formula
'(+ 3 (* (- 5 pi) 4 (/ 3 7))(* 15 2))
)

Math-formula contiene listas dentro de listas dentro delistas.

Supongamos que quisiéramos saber cuántos númerosestán sepultados en las profundidades de esta fórmula. Heaquí una función recursiva que lo averiguará:

(defun num-nums (mf)
(cond
((null mf) 0) ;; la lista vacía no contiene ninguno
((numberp (car mf)) ;; si el primer término es un número
(1+ (num-nums (cdr mf)))) ;; sumar al número en el resto
((atom (car mf)) ;; si es cualquier otro átomo
(num-nums (cdr mf))) ;; ignorarlo, contar el resto
(t (+ (num-nums (car mf)) ;; o se trata de una lista a contar
(num-nums (cdr mf)))))) ;; y sumar al numero en el resto

Pruebe esta función y examine su operaciónusando TRACE. Observe que la profundidad de recursión fluctúa amedida que las sublistas son procesadas.

>(num-nums math-formula)
1> (NUM-NUMS (+ 3 (* (- 5 PI) 4 (/ 3 7)) (* 15 2)))
2> (NUM-NUMS (3 (* (- 5 PI) 4 (/ 3 7)) (* 15 2)))
3> (NUM-NUMS ((* (- 5 PI) 4 (/ 3 7)) (* 15 2)))
4> (NUM-NUMS (* (- 5 PI) 4 (/ 3 7)))
5> (NUM-NUMS ((- 5 PI) 4 (/ 3 7)))
6> (NUM-NUMS (- 5 PI))
7> (NUM-NUMS (5 PI))
8> (NUM-NUMS (PI))
9> (NUM-NUMS NIL)
<9 (NUM-NUMS 0)
<8 (NUM-NUMS 0)
<7 (NUM-NUMS 1)
<6 (NUM-NUMS 1)
6> (NUM-NUMS (4 (/ 3 7)))
7> (NUM-NUMS ((/ 3 7)))
8> (NUM-NUMS (/ 3 7))
9> (NUM-NUMS (3 7))
10> (NUM-NUMS (7))
11> (NUM-NUMS NIL)
<11 (NUM-NUMS 0)
<10 (NUM-NUMS 1)
<9 (NUM-NUMS 2)
<8 (NUM-NUMS 2)
8> (NUM-NUMS NIL)
<8 (NUM-NUMS 0)
<7 (NUM-NUMS 2)
<6 (NUM-NUMS 3)
<5 (NUM-NUMS 4)
<4 (NUM-NUMS 4)
4> (NUM-NUMS ((* 15 2)))
5> (NUM-NUMS (* 15 2))
6> (NUM-NUMS (15 2))
7> (NUM-NUMS (2))
8> (NUM-NUMS NIL)
<8 (NUM-NUMS 0)
<7 (NUM-NUMS 1)
<6 (NUM-NUMS 2)
<5 (NUM-NUMS 2)
5> (NUM-NUMS NIL)
<5 (NUM-NUMS 0)
<4 (NUM-NUMS 2)
<3 (NUM-NUMS 6)
<2 (NUM-NUMS 7)
<1 (NUM-NUMS 7)
7

Sería difícil definir num-nums de formaiterativa. No es imposible, pero exige el saber utilizar una pila para simularla recursión.

Muchas tareas de inteligencia artificial implican el buscar a travésde estructuras anidadas. Por ejemplo, las representaciones en árbol delos movimientos en un juego se representan mejor como listas anidadas. Examinareste árbol implica un rastreo recursivo a través del mismo. Paraeste tipo de aplicación las funciones recursivas resultan unaherramienta esencial.

¿Cuándo debemos utilizar la iteración y cuándola recursión? Hay por lo menos estos tres factores a considerar:

(1)
La funciones iterativas son usualmente más rápidas que sus contrapartes recursivas. Si la velocidad es importante, normalmente usaríamos la iteración.
(2)
Si la memoria de pila es un limitante, se preferirá la iteración sobre la recursión.
(3)
Algunos procedimientos se programan de manera recursiva de forma muynatural, y resultan prácticamente inabordables iterativamente.Aquí la elección es clara.

Inicio |Índice