Año 2011 Cátedra: Computación Profesor: Mgr. Ma. del Carmen Varaldo Apunte sobre RECURSIVIDAD Concepto: Una definición recursiva es aquélla en la que el objeto que se define forma parte de la definición. Ejemplo: “Un descendiente del Sr. Pérez” Una persona es descendiente del Sr. Pérez si: (1) es un hijo del Sr. Pérez, o (2) es un hijo de un descendiente del Sr. Pérez. La condición (1) se denomina salida de la definición. La condición (2) se denomina parte recursiva propiamente dicha. Funciones recursivas: Ejemplo 1: Factorial de un número entero no negativo definido en modo recursivo. n! = 1 si n(n − 1)! si n=0 n>0 En Pascal se escribe ası́: function factorial (n:byte) : real; begin if n = 0 then factorial := 1 else factorial := n∗ factorial(n − 1); end; Ejemplo 2: Serie de Fibonacci 1, 1, 2, 3, 5, 8, 13, . . . Fib(1) = Fib(2) = Fib(3) = Fib(4) = En general, 1 1 Fib(2) + Fib(1) Fib(3) + Fib(2) Fib(n) = 1 si Fib(n − 1) + Fib(n − 2) si 1 n = 1, n = 2 n≥3 En Pascal se escribe ası́: function fibonacci (n:byte) : word; begin if n = 1 or n = 2 then fibonacci := 1 else fibonacci := fibonacci(n-1) + fibonacci(n-2); end; En el caso que se reemplace el parámetro n por 5, esta función será llamada de la siguiente manera fibonacci(2) fibonacci(3) % & fibonacci(1) % fibonacci(4) & fibonaccii(2) fibonacci(5) % & fibonacci(2) fibonacci(3) % & fibonacci(1) Volviendo hacia atrás sobre los llamados a la función y sabiendo que f ibonacci(2) = f ibonacci(1) = 1 se deduce que f ibonacci(5) = 5. Observe, además, que algunos de los cálculos se repiten, por ejemplo fibonacci(1). Existe otro método de resolver este problema a través de una forma iterativa, no recursiva. Se presenta la siguiente función: 2 function fibo (n:byte) : word; var a, b, f, i : word begin a := 1; b := 1; if n = 1 or n = 2 then f := 1 else for i := 3 to n do begin f := b + a; a := b; b := f ; end; f ibo := f ; end; No siempre es posible pasar de una forma recursiva a una iterativa. Cuando una rutina recursiva se llama recursivamente a sı́ misma varias veces, para cada llamada se crean copias independientes de las variables declaradas en el subprograma. A pesar de que la recursión permite representar en forma clara y elegante muchos algoritmos, sin embargo, el costo de memoria y tiempo que requiere su realización, puede implicar que para determinados algoritmos no sea conveniente su utilización. Procedimientos recursivos: Ejemplo 1: En Pascal se tiene: procedure Q (Num1,Num2 : integer); begin if N um2 ≤ 0 then Writeln else begin Q(N um1 − 1, N um2 − 1); Write(Num1:1); Q(N um1 + 1, N um2 − 1); end; end; Observe que si se reemplaza Num1 por 4 y Num2 por 2, se estarı́a invocando el procedimiento de la siguiente manera: 3 Q(2, 0) Write(Num1:1) Q(3, 1) → Q(4, 0) Write(Num1:1) escribe 4 Q(4, 2) → Q(4, 0) Write(Num1:1) Q(5, 1) → Q(6, 0) cambio de renglón escribe 3 cambio de renglón cambio de renglón escribe 5 cambio de renglón La salida por pantalla es: 3 4 5 Ejemplo 2: Las Torres de Hanói es un rompecabezas o juego matemático inventado en 1883 por el matemático francés Éduard Lucas. El juego, en su forma más tradicional, consiste en tres varillas verticales. En una de las varillas se apila un número indeterminado de discos (elaborados de madera) que determinará la complejidad de la solución, por regla general se consideran ocho discos. Los discos se apilan sobre una varilla en tamaño decreciente. No hay dos discos iguales, y todos ellos están apilados de mayor a menor radio en una de las varillas, quedando las otras dos varillas vacantes. El juego consiste en pasar todos los discos de la varilla ocupada (es decir la que posee la torre) a una de las otras varillas vacantes. Para realizar este objetivo, es necesario seguir tres simples reglas: 1. Sólo se puede mover un disco cada vez. 2. Un disco de mayor tamaño no puede descansar sobre uno más pequeño que él mismo. 3. Sólo puedes desplazar el disco que se encuentre arriba en cada varilla. Existen diversas formas de realizar la solución final, todas ellas siguiendo estrategias diversas. El siguiente algoritmo resuelve este juego en forma recursiva: Program hanoi; uses crt; var i,total:integer; c:char; procedure movertorre(altura,deaguja,haciaaguja,useaguja:integer); procedure moverdisco(salida,ponsobre:integer); 4 begin writeln(salida,’->’,ponsobre); i:=i+1; if (i mod 20=0) then begin writeln(’Presione una tecla’); c:=ReadKey; end; end; begin if altura>0 then begin movertorre(altura-1,deaguja,useaguja,haciaaguja); moverdisco(deaguja,haciaaguja); movertorre(altura-1,useaguja,haciaaguja,deaguja); end; end; begin i:=0; writeln(’ingresar cantidad de discos’); readln(total); movertorre(total,1,3,2); end. Bibliografı́a: 1. “Matemática Discreta y Combinatoria”, Ralph Grimaldi 2. “Programación en TURBO PASCAL 7”, Luis Joyanes Aguilar, McGrawHill 5