Está en la página 1de 22

Elementos de Programaci on y Estructura de Datos Versi on 0.

1
Maria Leticia Blanco Coca 18 de marzo de 2009

Tabla de Contenido
Lista de tablas Lista de guras 1. Recursividad 1.1. Concepto . . . . . . . . . . . . . . 1.2. Denici on de proceso recursivo . . . 1.2.1. Parte Recursiva . . . . . . . 1.2.2. Parte B asica . . . . . . . . . 1.2.3. Condiciones de Contexto . . 1.3. Correctitud de recursi on . . . . . . 1.3.1. Regla del caso b asico . . . . 1.3.2. Regla de progreso . . . . . . 1.3.3. Regla del dise no . . . . . . . 1.3.4. Regla del inter es compuesto 1.4. Dise no de procesos recursivos . . . 1.4.1. Deducci on . . . . . . . . . . 1.4.2. Inducci on . . . . . . . . . . 1.5. Ejecuci on de recursi on . . . . . . . 1.6. Recursi on directa . . . . . . . . . . 1.7. Recursi on indirecta . . . . . . . . . 1.8. Ejercicios . . . . . . . . . . . . . .
I I

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

1 1 1 2 3 3 4 4 5 6 6 7 7 9 10 12 12 13

ii

TABLA DE CONTENIDO

Cap tulo 1 Recursividad


1.1. Concepto

La recursividad es un elemento de programaci on que provee un mecanismo poderoso para la fase de dise no. La recursividad es una alternativa a la iteraci on y se puede denir en t erminos generales de la siguiente forma: Alguna cosa se dene como recursiva si est a denida en t erminos de s misma La recursividad se puede presentar en muchos objetos, por ejemplo la famosa mu neca rusa (ver Figura 1.1) tradicional denominada matrioska, creada en 1890, cuya originalidad consiste en que se encuentran huecas por dentro, de tal manera que en su interior albergan una nueva mu neca, y esta a su vez a otra, y esta a su vez otra, en un n umero variable que puede ir desde cinco hasta el n umero que se desee. Otro ejemplo es la gura 1.2 que ilustra una imagen recursiva formada por un tri angulo. Cada tri angulo est a compuesto de otros m as peque nos, compuestos a su vez de la misma estructura recursiva.

1.2.

Denici on de proceso recursivo

Un proceso es recursivo, si est a denido en t erminos de s mismo. Uno de los ejemplos m as cl asicos de la recursividad es la funci on factorial, cuya denici on es: n! = n * (n - 1)! 1

CAP ITULO 1. RECURSIVIDAD

Figura 1.1: Modelo Mu neca matrioska 0! = 1 n N La funci on factorial est a denida por el s mbolo !, que puede ser observado en ambos lados de la denici on n! = n * (n - 1)! Es decir, para poder calcular el f actorial de n, debemos calcular el f actorial de n - 1, se necesita de la misma funci on; por lo que, se dice que esta denici on del factorial es recursiva. Sin embargo esta denici on, involucra varios aspectos importantes que se deben tomar en cuenta cuando se dene procesos recursivos, continuamos con el ejemplo anterior y en esta decni on se puede identicar tres elementos importantes en la denici on: la parte recursiva, la parte b asica y las condiciones de contexto.

1.2.1.

Parte Recursiva

La parte recursiva de la denici on es aquella en la que se advierte la denici on del proceso en t erminos de si mismo: PR: n! = n * (n - 1)! Esta parte es la que cualica a un proceso como recursivo.

DE PROCESO RECURSIVO 1.2. DEFINICION

Figura 1.2: Modelo Tri angulo

1.2.2.

Parte B asica

La parte b asica de un proceso, se llama a aquella que no est a denida en t erminos de s mismo, y que muestra la obtenci on de un resultado directo: PB: 0! = 1 Esta denici on es muy importante, en la recursividad ya que asegura que en el alg un momento es posible obtener una respuesta.

1.2.3.

Condiciones de Contexto

En computaci on, las condiciones de contexto son un concepto impl cito a la hora de denir o concebir un proceso automatizado, en caso de la recursi on este aspecto tambi en es importante ya que determina los valores v alidos sobre los cuales se ha denido el proceso: CC: n N esta l nea en la denici on, pone candados fuertes al uso correcto del factorial. La denici on no es u til para n umeros negativos ni para n umeros reales. En las secciones adelaate veremos la importancia de las condiciones de contexto cuando se trata de asegurar la correctitud de la denici on.

CAP ITULO 1. RECURSIVIDAD

1.3.

Correctitud de recursi on

Un proceso es correcto si: Resuelve el problema para el cual fue dise nado, Para cada entrada v alida, genera la salida(resultado/efecto) deseada Termina en un tiempo nito Para, en fase de dise no asegurar la escritura de un proceso recursivo correcto, se debe cumplir las siguientes reglas:

1.3.1.

Regla del caso b asico

Los procesos se ejecutan en distintos casos (escenarios), esta regla indica que debe haber un caso especial para el cual el proceso no haga uso de la denici on recursiva, es decir, no utilizar la parte recursiva. Sino utilizar sica. El caso particular para el cual fue denido la parte b la parte ba asica debe cumplir las condiciones de contexto estipuladas para la denici on, si es as este caso se denomina caso b asico. La parte b asica de la denici on del factorial, se ha denido para un caso particular 0. Este caso cumple la regla del caso b asico, si y solamente si, el 0 pertenece y cumple las condiciones de contexto de la denici on. Es importante entonces, a la hora de denir, no s olamente tener una parte b asica, sino asegurar que el caso para el cual se ha denido esta parte, cumpla la regla del caso b asico. En la denici on de factorial: PR: n! = n * (n - 1)! PB: 0! = 1 CC: n N El 0 es un caso b asico ya que 0 N Formalizando, sea P B : proc(cb) = res y CC : n tipo, se dice que cb cumple la regla del caso b asico, si y s olo s , cb tipo. Esta regla, coadyuva a asegurar la terminaci on del proceso en un tiempo nito.

1.3. CORRECTITUD DE RECURSION

1.3.2.

Regla de progreso

La regla del progreso, indica que toda denici on recursiva debe en su llamada recursiva progresar hacia el caso b asico. La parte recursiva de un proceso, hace uso del mismo proceso, y funciona porque trabaja sobre distintos casos, usualmente estos casos son las entradas a los procesos. Entonces se dice que los casos de las sucesivas llamadas recursivas deben progresar al caso b asico, para asegurar la nalizaci on del proceso y as obtener un resultado (si fuera el caso). Consideremos nuevamente la denici on del factorial, en su parte recursiva y sus condiciones de contexto: PR: n! = n * (n - 1)! CC: n N Es evidente que la parte recursiva se ejecutar a cuando el valor de n = 0, pero por las condiciones de contexto, la u nica posibilidad de n es que N , por lo que se puede deducir que: n>0 Por lo que la llamada recursiva al factorial ser a (n 1)! Esto quiere decir, que el caso para esta llamada ser a n 1, pues bien, como n = 0 y n N , entonces (n1) 0 lo que signica que n 1 esta m as pr oximo a 0 que n. Por lo tanto si n se reduce en 1 estaremos progresando a 0. En este caso la denici on de la parte recursiva, cumple la regla del progreso. Formalizando, sea P R : proc(c1) = proc(c2) y cb es caso b asico ; Se dice que PR cumple con la regla del progreso, si y s olo s , progresa progresa progresa c1 c2 . . . cb Esta regla aporta a que el proceso para cada entrada v alida, genera la salida(resultado/efecto) deseada y que termine en un tiempo nito.

CAP ITULO 1. RECURSIVIDAD

1.3.3.

Regla del dise no

Un proceso recursivo, debe ser correcto en todas sus partes. Aparentemensica de la denici te no es dif cil vericar la correctitud de la parte ba on, pero en la parte recursiva es un m as dif cil vericar, por lo que la forma de hacerlo es asegurando el dise no del proceso, y se dice que el proceso recursivo es correcto s y solamente s la llamada recursiva es correcta. En el caso del factorial: n! es correcto, si y s olamente s (n 1)! es correcto. Formalizando, sea: P R : proc(c1) = proc(c2) y Se dice que proc(c1) es correcto si y s olamente s proc(c2) es correcto Esta regla aporta a que el proceso resuelva el problema para el cual fue dise nado.

1.3.4.

Regla del inter es compuesto

Esta regla trata de que en lo posible se dise ne procesos ecientes y dice: efecto de las sucesivas llamadas recursivas al proceso no se deber a ejecutar m as de una vez el proceso para un mismo caso. Este problema usualmente se encuentra cuando el proceso se dene en base a dos llamadas recursivas, y es probable que por ambas se repita un caso. El factorial no rompe esta regla, pero un otro ejemplo cl asico, es encontrar el n-simo n umero de la serie de Fibonacci. La serie de Fibonacci es una secuencia de n umeros naturales cuyos dos primeros n umeros son datos y a partir del tercero se autogeneran sobre la base de los dos anteriores, la serie tiene la siguiente forma: 0, 1, 1, 2, 3, 5, 8, . . . En este ejemplo los n umeros base son: 0 y 1 que vendr an a ser el 1er. y 2do. n umeros de la serie. Por lo que si se quiere calcular el 8vo. n umero de la serie se necesita tener el 7mo. y 6to. n umero previamente. Por regla general, para calcular el n-simo n umero se requiere del (n-1)-simo y del (n-2)-simo t ermino de la serie, salvo para el 1ro. que es 0 y para el 2do. que es 1; por lo que es correcto realizar la siguiente denici on:

DE PROCESOS RECURSIVOS 1.4. DISENO PR: f ib(n) = f ib(n 1) + f ib(n 2) PB: f ib(1) = 0 PB: f ib(2) = 1 CC: n N

Este es un ejemplo de un proceso recursivo con m as de una parte b asica. En este caso para calcular el 4to. n umero Fibonacci se debe calcular el 3er. Fibonacci y el 2do. Fibonacci. Pero para calcular el 3er. Fibonacci se necesita calcular el 2do. y el 1er. En este momento ya se ha calculado dos veces el 2do. Fibonacci, tratando de encontrar el resultado del 4to Fibonacci. Por lo que, la denici on del proceso incumple la regla del inter es compuesto.

1.4.

Dise no de procesos recursivos

La recursi on es un elemento poderoso de programaci on simple, pero complejo. Para poder dise nar procesos recursivos, se utiliza dos principios matem aticos, que desde distintos puntos llevan a obtener las partes de un proceso recursivo de forma sistem atica y apoyan el cumplimiento de la regla del dise no.

1.4.1.

Deducci on

Consiste en analizar el problema desde sus casos m as sencillos y conocidos; para continuar con casos sucesivos e intentar deducir una regla de generalizaci on. Por ejemplo se quiere encontrar la cantidad de asteriscos que se requieren para dibujar un tri angulo rect angulo is oceles de base n, de acuerdo a la Figura 1.3. Debemos primero dar un nombre a nuestro problema numAst(n) y encontrar los casos m as simples y sobre la base de este conocimiento tratar de encontrar casos m as dif ciles o mayores, entonces analicemos: numAst(0) es 0 que es el caso m as simple lo u nico que sabemos es el dato de la base 0 numAst(1) es 1, pero para calcular este resultado ya sabemos m as cosas: el resultado numAst(0) y 1 que es la base como dato de entrada... numAst(2) es 3, para calcular este resultado ya sabemos m as cosas: el resultado numAst(1) y 2 que es la base como dato de

CAP ITULO 1. RECURSIVIDAD

Figura 1.3: Numeros triangulares de Pit agoras entrada... numAst(3) es 6, pero para calcular este resultado ya sabemos m as cosas: el resultado numAst(2) y 3 que es la base como dato de entrada... Ahora tratemos de encontrar una relaci on entre el resultado y los que se conoce para poder deducir una regla general: numAst(0) = 0, este no cambia es el caso m as sencillo numAst(1) = 1+numAst(0) reemplazando se tiene numAst(1) = 1+01 numAst(2) = 2+numAst(1) reemplazando se tiene numAst(2) = 2+13 numAst(3) = 3+numAst(2) reemplazando se tiene numAst(3) = 3+36 numAst(4) = 4+numAst(3) reemplazando se tiene numAst(3) = 4 + 6 10 . . . generalizando . . . numAst(n) = n + numAst(n 1)

DE PROCESOS RECURSIVOS 1.4. DISENO Hasta aqu , se ha denido un dominio de valores v alidos para el proceso e indirectamente se ha asegurado que se cumpla la regla del progreso, ya que se ha deducido a partir del caso m as simple - que vendr a a ser el caso b asico - a un caso general n que son valores mayores 0. Al nalizar la denici on queda: PR: numAst(n) = n + numAst(n 1) PB: numAst(0) = 0 CC: n N numAst(n) = 0 si n = 0 n + numAst(n 1) otro caso

1.4.2.

Inducci on

La inducci on es otra de las herramientas que se utilizan para dise nar un proceso recursivo, a diferencia de la deducci on se parte de una hipotesis y sobre esta se genera una generalizaci on para un caso mayor: Por ejemplo, se desea encontrar la cantidad de digitos que tiene un n umero entero positivo. En este caso, aplicar deducci on es un tanto complicado, por lo que asumiremos que casos menores ya se conocen. El problema se puede denominar cantDig (n) - cantidad de d gitos del n umero n, procedamos con el an alisis: En este problema no interesa el valor del n umero, sino m as bien su estructura; por lo que se puede decir que el n umero estructuralmente es una secuencia de d gitos, n = ddddddd . . . dd, y que: cantDig (n) = cantDig (ddd . . . dd)) si a la estructura de n le quitamos un d gito, lo que queda - n1 sigue siendo un n umero y tambi en tiene cantidad de d gitos: n = ddd . . . dd d
n1

ahora supongamos que el resultado de calcular cantDig (n1) es m y adem as es correcto. Con este conocimiento, cu antos d gitos tendr a n?, La respuesta es f acil - m + 1, por lo que: cantDig (n) = cantDig (n1) + 1 Lo siguiente que hay que hacer es, denir la forma de encontrar n1 dado que se tiene n, o que es lo mismo, cu al es la manera m as

10

CAP ITULO 1. RECURSIVIDAD f acil de quitarle un d gito a n?, dividiendo entre 10 y el n umero sin un d gito viene a ser el cociente de la operaci on, entonces: n1 = n/10, reemplazando cantDig (n) = cantDig (n/10) + 1 Hasta aqu , se ha encontrado la parte recursiva de la denisica. ci on, lo que nos falta es la parte ba Cu ando dejaremos de dividir a n?, cuando n sea un n umero unid gito, en este caso la cantidad de d gitos de un n umero unid gito es 1. cantDig (n) = 1, n < 10 La denici on completa seria: P R : cantDig (n) = cantDig (n/10) + 1 P B : cantDig (n) = 1, n < 10 CC : n Z + cantDig (n) = 1 si n < 10 cantDig (n/10) + 1 otro caso

1.5.

Ejecuci on de recursi on

Por que la recursi on funciona?, en t erminos de ejecuci on cada llamada tiene su propio espacio y el puntero de ejecuci on respeta el orden de ejecuci on de forma estricta. Para poder mostrar una ejecuci on, escribiremos el c odigo en Java del proceso factorial, mostrado en la secci on 1.2, para ello se debe denominar la funci on, en nuestro caso llamaremos calcularF actorial(n) y su denici on: calcularF actorial(n) = El programa es: Ejem05 Factorial 1 si n = 0 n calcularF actorial(n 1) otro caso

Clase Factorial

/** * Proyecto Ejem05_Factorial * Clase que muestra la implementacion del metodo * recursivo calcularFactorial * * @author MLBC

DE RECURSION 1.5. EJECUCION * @version 01.09 */ public class Factorial { /** * Metodo que calcula el factorial de un numero * * @param n parametro de la funcion factorial * @return el factorial */ public int calcularFactorial(int n) { int factorial; if(n == 0) factorial = 1; else factorial = n * calcularFactorial(n-1); return factorial; } }

11

La ejecuci on del m etodo calcularF actorial(4) se realiza como se muestra en la Figura 1.4 Una vez que se tiene el c odigo, se observa que el m etodo calcularF actorial(n), utiliza dos variables: un par ametro - n - y una variable local - f actorial. Considerando los detalles de programaci on y la relaci on tiempo y espacio en la Figura 1.4 se tiene que para toda llamada a calcularF actorial(n) se denen los valores para n y f actorial para luego preguntar sobre el valor de n y dependiendo de la respuesta se procede a denir el f actorial con 1 o con la siguiente expresi on n calcularF actorial(n 1). Cada espacio representa una ejecuci on particular de calcularF actorial(n) y muestra cual de las dos posibles opciones de denir f actorial se ha tomado. En base a esta denici on se van generando nuevas llamadas al m etodo, las mismas que se denominan llamadas recursivas. En un instante de tiempo se observa que se tienen al mismo tiempo varios espacios locales 1 abiertos esperando terminar su ejecu1

Espacio de direcciones de memoria asociado a un proceso

12

CAP ITULO 1. RECURSIVIDAD

ci on. Pero tambi en se observa que el puntero de ejecuci on 2 se encuentra en exactamente un espacio, esto debido a que estamos procesando en un entorno no distribuido3 . La u nica vez que un espacio local desaparece, es cuando termina de ejecutar el m etodo y retorna el resultado y el puntero de ejecuci on al lugar donde fue originada la llamada. Al nalizar, todos los espacios locales se habr an cerrado y el puntero de ejecuci on retornar a a la primera llamada. Notar que: Tanto el par ametro n y la variable local f actorial, asumen distintos valores pero en distintos espacios lo cual, permite utilizar los mismos nombres en las diferentes llamadas. Que cada llamada (en el ejemplo del factorial) no tiene los mismos casos, por lo tanto son diferentes.

1.6.

Recursi on directa

Se denomina recursi on directa, cuando la denci on del proceso recursivo hace una llamada al mismo proceso en su parte recursiva. Hasta ahora todos los ejemplos que se han planteado son directos.

1.7.

Recursi on indirecta

Considere el problema de decidir si un n umero natural es par o no, la condici on es que no se puede usar la operaci on de divisi on, ni de m odulo. El razonamiento es muy sencillo, si el n umero es 0, entonces es par; caso contrario, si es mayor que 0, el n umero es par s olo si el anterior es impar. Formalicemos: esP ar(n) =
2

true si n = 0 esImpar(n 1) otro caso

Se dice entorno no distribuido, cuando la carga de ejecuci on descansa sobre un procesador

1.8. EJERCICIOS

13

Aqui no existe recursividad ya que la parte que no tiene soluci on directa no est a denida en t erminos de s misma. Pero a un nos falta denir esImpar(n). Pues bien, denamos esImpar(n): se sabe que el 0 no es impar, pero si el n umero fuera mayor que 0, este es impar, s y s olo s el anterior es par. Formalicemos: esImpar(n) = f alse si n = 0 esP ar(n 1) otro caso

esImpar(n) no es recursivo tampoco. Pero juntando las dos deniciones, podemos constatar que para decidir esP ar(n) se requiere de esImpar(n) y para decidir esImpar(n) se requiere de esP ar(n), de todas maneras si tenemos que usar esP ar(n) para el caso que no es b asico terminaremos usando nuevamente esP ar(n) (ver Figura 1.5). Este es un ejemplo de recursi on indirecta, que se presenta en esP ar(n) y tambi en en esImpar(n). La recursi on indirecta, se da cuando un proceso est a denido en t erminos de un segundo proceso y este segundo proceso est a denido en t erminos del primero. Este concepto puede darse entre varios procesos y generar llamadas c clicas, por ejemplo: el proceso1 llama al proceso2, el proceso2 usa el proceso3, el proceso3 llama al proceso4 y el proceso4 usa el proceso1. En este caso todos los procesos son recursivos indirectos.

1.8.

Ejercicios

1. Dise ne procesos recursivos, utilizando deducci on/inducci on, para los siguientes problemas: a ) Se desea calcular el ab . b ) Dada una secuencia de caracteres, encuentre la cantidad de vocales que tiene. Por ejemplo, sea la cadena contenedora, el resultado es 5. c ) Se tiene una cadena, la cual se debe rotar hacia la izquierda tantos caracteres como consonantes tenga al principio (de izquierda a derecha). Por ejemplo, sea la cadena crespo, el resultado es espocr, note que se ha rotado las consonates que la cadena original tiene al principio al nal de la cadena resultante.

14

CAP ITULO 1. RECURSIVIDAD d ) Recorte una cadena en posibles s labas, considerando que cada que aparece una vocal en la cadena posiblemente hasta ese caracter hay una s laba. Por ejemplo, dados los siguientes casos: Caso1: cada, el resultado es {ca, da} Caso2: oreja, el resultado es {o, re, ja} Caso3: programacion, el resultado es {pro, gra, ma, ci, o, n} Caso4: crespo, el resultado es {cre, spo} e ) Sume los elementos de una secuencia de n umeros. f ) Encuentre la media aritm etica de una secuencia de n umeros. g ) Se tiene un histograma creciente y se desea encontrar el histograma transpuesto correspondiente. h ) Se dice que un n umero es bomba cuando el n umero. i ) Se quiere saber si un n umero es perfecto o no. Se dice que un n umero es perfecto cuando las suma de sus divisores, excepto el propio n umero, es igual al n umero original. Por ejemplo, el n umero 6 es perfecto, ya que la suma de sus divisores 1 + 2 + 3 = 6 j ) Dado un n umero natural, se desea encontrar el n umero invertido. k ) Dado un n umero natural, se desea encontrar su equivalente en funci on suc. Se sabe que el 0 es igual a 0, pero el 1 es igual a suc(0), el 2 es a suc(suc(0)) y as sucesivamente. Por ejemplo, dados los siguientes casos: Caso1: 3, el resultado es suc(suc(suc(0))) Caso2: 5, el resultado es suc(suc(suc(suc(suc(0))))) Caso3: 0, el resultado es 0 l ) Se pide realizar el proceso inverso del anterior ejercicio, es decir se recibe una cadena, y se debe encontrar el n umero original. Por ejemplo, dados los siguientes casos: Caso1: suc(suc(suc(0))), el resultado es 3 Caso2: suc(suc(suc(suc(suc(0))))), el resultado es 5 Caso3: 0, el resultado es 0

1.8. EJERCICIOS

15

m ) Se pide realizar el (los) m etodo(s) necesario(s) recursivo(s) para encontrar todas la combinaciones posibles de una cadena de n caracteres. Por ejemplo, si se tiene los caracteres A, B, C, D, el resultado ser a: ABCD, BACD, BCAD, CBAD, CABD, ACBD, BCDA, DBCA, BDCA, CDAB, DCAB, DACB, ADCB, ACDB, ABDC, BADC, BDAC, DBAC n ) Una forma de encontrar el cuadrado de n es sumando los n primeros n umeros impares. Realiza el (los) m etodo(s) recursivo(s) para 2 encontrar n .

3. Dados los siguientes m 2. etodos, identique la(s) parte(s) recursiva(s) sica(s), e indique si cumplen las reglas: del caso b y ba asico, del progreso, de dise no y de inter es compuesto. Realice la ejecuci on e indique que hacen. a ) Para valores x, y Z , para una ejecuci on considere los siguientes valores: x = 5 e y = 7 public int dudoso1(int x, int y) { int res = 0; if(x < 0 || y <0) res = x - y; else res = dudoso1(x-1, y) + dudoso1(x, y-1); return res; } b ) Para valores a, b Z + . public int dudoso3(int a, int b) { int res = 0; if(a < b) res = a; else

16

CAP ITULO 1. RECURSIVIDAD if(b == a) res = dudoso3(a, b); else res = a * dudoso3(a - b, b); return res; } c ) Para valores a, b Z + . Para una ejecuci on considere los valores a=8yb=4 public int dudoso2(int a, int b) { int res = 0; if(b == 1) res = a; else if(b%2 == 0) res = dudoso2(a, b/2) * dudoso2(a, b/2); else res = a * dudoso2(a, b/2) * dudoso2(a, b/2); return res; }

1.8. EJERCICIOS

17

Figura 1.4: Ejecuci on de calcularF actorial

18

CAP ITULO 1. RECURSIVIDAD

Figura 1.5: Ejecuci on de esP ar

También podría gustarte