Un objeto se dice recursivo si está definido en términos de sí mismo.

Documentos relacionados
Asumiremos que se dispone de procedimientos para leer y escribir caracteres. Se desarrollan algunas funciones primitivas que nos serán útiles.

Universidad de Valladolid. Departamento de informática. Campus de Segovia. Estructura de datos Tema 1: Recursividad. Prof. Montserrat Serrano Montero

Recursión. Recursión continuación

Departamento de Informática Universidad de Valladolid Campus de Segovia TEMA 1: RECURSIÓN

Puede clasificarse en cuatro componentes básicas la eficiencia de un programa:

Recursividad Definición

1. ESTRUCTURA DE UN PROGRAMA PASCAL Todo programa escrito en lenguaje Pascal, del más simple al más complejo, tiene la siguiente estructura:

Recursividad. Definición. Diseño de Algoritmos Recursivos

Dra. Jessica Andrea Carballido

Uno de los conceptos más útiles en ciencias de la computación es la pila.

Arreglos y Subrangos

Estudiemos el siguiente problema, propuesto por Wirth y desarrollado por Dijkstra: Una lista de las primeras secuencias que cumplen es:

Manual de turbo pascal

Introducción a la Programación

Resolución de Problemas y Algoritmos

Dra. Jessica Andrea Carballido

Módulo 7: Sentencias de control en Pascal

Arreglos y Subrangos

Dra. Jessica Andrea Carballido

FUNDAMENTOS DE OBJECT PASCAL

Qué es la recursividad?

Trabajo Práctico Nº 4 Iteración

Resolución de Problemas y Algoritmos Segundo cuatrimestre 2015 Clase 11: Construcción de primitivas (Funciones)

'type' <nombre conjunto> '=' 'SET OF' <tipo base>

La recursividad forma parte del repertorio para resolver problemas en Computación y es de los métodos más poderosos y usados.

Apunte Laboratorio ALPI - El lenguaje de programación Pascal

Tema 06: Recursividad

Tipos y Estructuras de Control. Dpto. de Ciencias e Ingeniería de la Computación UNIVERSIDAD NACIONAL DEL SUR

FUNDAMENTOS DE PROGRAMACIÓN LABORATORIO SESIÓN 2

Primer Parcial. Programación 1 Instituto de Computación Año 2011

Iteración Diagrama de SINTAXIS: IF

EXAMENES RESUELTOS DE PROGRAMACION I

Primer Parcial. Programación 1 Instituto de Computación Año 2017

Resolución de Problemas y Algoritmos

Declaración de Procedimientos

Resolución de Problemas y Algoritmos

UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 27. Verificación analítica de programas.

6. Estructuras básicas de control 1. Pseudocódigo

UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 2. Acciones Primitivas.

APUNTES DE CÁTEDRA: ARREGLOS MULTIDIMENSIONALES

Unidad II: Análisis semántico

Análisis de algoritmos. Recursividad

Módulo. = Asignación = = Comp. de igualdad!= Com. de desigualdad <= Comp. menor o igual >= Comp. mayor o igual AND lógico OR lógica.

Temario. Tipos de recursión. Eficiencia y recursión

Resolución de Problemas y Algoritmos Segundo cuatrimestre de 2015 Clase 18: Recursión - Problemas clásicos

U nidad 6: A rreglos: U nidim ensionales y m ultidim ensionales

Resolución de Problemas y Algoritmos Clase 6: Repetición (continuación)

Programación modular en Pascal

Controla el flujo de tokens reconocidos por parte del analizador léxico. 4.2 Introduccion a las gramaticas libres de contexto y arboles de derivacion

Concepto de Recursión. Características de algoritmos recursivos. Ejemplos

Repetición Condicional

Estructuras de Programación

28/10/2016. Procesamiento de Secuencias. Procesamiento de Secuencias. Procesamiento de Secuencias. Procesamiento de Secuencias

Dra. Jessica Andrea Carballido

Jesús Ravelo Kelwin Fernández Universidad Simón Bolívar Dpto. de Computación y Tecnología de la Información

Recursividad. Definición de Recursividad: Técnica de programación muy potente que puede ser usada en lugar de la iteración.

Trabajo Práctico Nº 06

21/03/2018. Variables y Constantes. Los datos de un programa están representados por variables o constantes y tienen asociado un tipo.

Tema 1 INTRODUCCIÓN A LOS LENGUAJES DE PROGRAMACIÓN

Análisis y Programación

Tema 7. Recursividad. J.T.P. Maria Eugenia Valesani - Programacion 1 - Fa.Ce.Na.

Listas y Recursión. Taller de Álgebra I. Primer Cuatrimestre de 2015

Análisis de algoritmos

3.2. Programación estructurada. Principal. Modulo 1 Modulo 2 Modulo 3 Modulo 4. Modulo Modulo Modulo 3 1 Modulo 4 1 Modulo 4 2. Pág.

Una clave Definición informal La clave debe contener una secuencia de una o más letras seguidas por uno o más dígitos

Departamento de Informática Universidad de Valladolid Campus de Segovia LABORATORIO: INTRODUCCIÓN A LAS UNIDADES EN TURBO PASCAL

TEMA 3: Estructuras de Control: Iterativas

Índice general 7. Presentación 15

Estructura de Datos. Recursividad. Primer Semestre, Indice

Componentes Básicos. InCo. InCo Componentes Básicos 1 / 28

Iteración Diagrama de SINTAXIS: IF

SUBRANGO ENUMERADOS CONJUNTOS

Universidad de Valladolid. Departamento de informática. Campus de Segovia. Estructura de datos Tema 4: Ordenación. Prof. Montserrat Serrano Montero

Dra. Jessica Andrea Carballido

FACULTADE DE INFORMÁTICA Departamento de Computación Estructura de Datos e da Información. Ejercicios de recursividad

UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 3. Acciones Estructuradas.

Si L es recursivo, entonces es recursivamente numerable

ESTRUCTURA SECUENCIAL ESTRUCTURA SELECTIVA

4.5 Ligado de Variables en Scheme

El lenguaje de programación JKL

RECURSIVIDAD. Prof. Ing. M.Sc. Fulbia Torres

Departamento de Informática Universidad de Valladolid Campus de Segovia. TEMA 4: TIPOS ABSTRACTOS DE DATOS (TADs)

Estructura de datos y Programación

Unidades en PASCAL (Units)

EXAMENES RESUELTOS DE PROGRAMACION I

UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 21. Registros. Records.

ALGORITMOS Y ESTRUCTURAS DE DATOS EJERCICIOS RESUELTOS SEGUNDA PARTE

Programcaión Básica. Secuencias de Control y Repetición. Arturo Vega González.

Diseño de Compiladores I. Estructura General de un Compilador

Analizador Léxico. Programación II Margarita Álvarez. Analizador Léxico - Funciones

Introducción. Algoritmos y Complejidad. Algoritmos y Algoritmia. Introducción. Problemas e instancias. Pablo R. Fillottrani

Algoritmos y Complejidad

Subprogramas en Fortran 90. Seminario de Computación 2009

Recursividad. Dept. Ciencias de la Computación e I.A. Universidad de Granada

RECURSION. Se deben hacer cuatro preguntas para construir una solución recursiva:

GUIA EXAMEN FINAL/EXTRAORDINARIO

LABORATORIO DE PROGRAMACIÓN II Problemas HOJA 1 RECURSIVIDAD

14/03/2018. Problemas, Algoritmos y Programas. Problemas, Algoritmos y Programas. Programas y Lenguajes. Programas y Lenguajes. Programas y Lenguajes

Transcripción:

19. RECURSION 19.1. Conceptos. Cualquier procedimiento o función pueden contener, en su bloque de acciones ejecutables, llamados a otros procedimientos que sean accesibles. Si puede llamarse a cualquier procedimiento accesible, entonces un procedimiento puede llamarse a sí mismo. Esta autoreactivación se denomina recursión. Una cadena de llamados recursivos debe terminar en algún momento; por esta razón los subprogramas recursivos deben colocar dentro de una instrucción condicionada el llamado recursivo. El empleo de un identificador de subprograma dentro del texto del mismo subprograma implica la ejecución recursiva del mismo. Más específicamente, la ocurrencia de un llamado a una función, dentro de una expresión perteneciente al bloque asociado a la misma función, implica la ejecución recursiva de la función. Su aplicación es natural en aquellos algoritmos definidos recursivamente; y también cuando se emplean estructuras de datos que hayan sido definidas recursivamente. Sin embargo, siempre es posible desarrollar un algoritmo repetitivo en lugar del recursivo; lo cual trá ventajas en menor ocupación de memoria y mayor velocidad de ejecución. Cada vez que se realiza una autoinvocación, se crea espacio para variables y parámetros valor; es decir, a medida que aumentan los llamados recursivos existen varias instancias (o encarnaciones) de las variables. Así también habrá que considerar todas las instrucciones que permitan retornar a los diferentes puntos de llamado. Esto también implica que el programador debe asegurarse que los niveles de recursión no sean excesivamente altos; ya que esto podría copar la memoria disponible. Un objeto se dice recursivo si está definido en términos de sí mismo. 19.2. Ejemplos de definiciones recursivas. Prof. Leopoldo Silva Bijit. 07-07-2003 242

El concepto de recursión es particularmente poderoso en definiciones matemáticas; veamos algunos ejemplos: a) Número natural: i) 1 es un número natural. ii) el sucesor de un número natural es un número natural. b) La función factorial, para enteros no negativos: i) 0! = 1 ii) Si n>0 entonces n! = n*(n-1)! c) Máximo común divisor, para enteros positivos. mcd(m, n) i) mcd(m, 0) = m ii) Si n>0 entonces mcd(m, n) = mcd(n, m mod n) d) Números de Fibonacci: i) fib(0) = 1; fib(1) = 1 ii) fib(n) = fib(n-1)+fib(n-2) para n>1 En Pascal, pueden diseñarse, casi directamente las siguientes funciones: a) function fact(i:integer):integer; if i>0 then fact:=i*fact(i-1) else fact:=1 b) function mcd(m,n:integer):integer; if n=0 then mcd:=m else mcd:=mcd(n,m mod n) c) function fib(n:integer):integer; if n=0 then fib:=0 Prof. Leopoldo Silva Bijit. 07-07-2003 243

else if n=1 then fib:=1 else fib:=fib(n-1)+fib(n-2) UNIVERSIDAD TECNICA FEDERICO SANTA MARIA Algunos de estos ejemplos han sido desarrollados antes por algoritmos repetitivos. Nótese que los llamados recursivos están dentro de estructuras de control condicional. La potencia de la recursión se basa en la posibilidad de definir un conjunto infinito de objetos por una sentencia finita. Del mismo modo un número infinito de computaciones puede describirse por un programa finito recursivo. Las etapas previas de compilación, el análisis léxico y sintáctico pueden describirse recursivamente; por esta razón los programas que los implementan suelen ser recursivos. Se han ilustrado algunas funciones recursivas, pero también es posible desarrollar procedimientos recursivos. 19.3. Ejemplos. 19.3.1. Permutaciones. Una permutación de una secuencia de objetos es una redisposición de los mismos. Por ejemplo las permutaciones de 123 son: 123, 132, 213, 231, 312 y 321. Permutando las letras de una palabra se obtiene un anagrama. Por ejemplo: roma, amor, omar, mora, ramo. El número de permutaciones de n objetos es n!. En la primera posición es posible colocar cualesquiera de los n objetos; en la segunda existen n-1 posibilidades, ya que se asume utilizado un objeto en la primera posición. En la última posición sólo es posible colocar el que queda. El siguiente programa genera las permutaciones de 123. program permute(output); var i,j,k : integer; Prof. Leopoldo Silva Bijit. 07-07-2003 244

for i:=1 to 3 do for j:=1 to 3 do for k:=1 to 3 do if (i<>j) and (i<>k) and (j<>k) then writeln(i,j,k);. El programa efectúa 3*3*3 iteraciones; es decir, 27. Mientras que el número de permutaciones es 3! ; es decir, 6. Una forma de disminuir las iteraciones es por ejemplo, no realizar el tercer lazo (el más interno) si las dos variables anteriores son iguales. Pero si se desea obtener las permutaciones de un número de objetos mayor (y que no sean necesariamente números) debe pensarse en un algoritmo diferente, que sea más eficiente. Si se escriben las permutaciones de 1234 y se analiza en detalle la secuencia, podremos plantear para las permutaciones de n objetos distintos a[1], a[2],..., a[n] el siguiente algoritmo recursivo. Sea permute(n) la acción que obtiene las permutaciones de los n objetos. Su implementación se descompone en: a) Se mantiene a[n] en su lugar; y se generan todas las permutaciones de los n-1 objetos restantes. Es decir se invoca a permute(n-1). b) Se repite a) previo cambio de a[n] con a[1]. c) Se sigue repitio a) efectuando el cambio a[n] con a[i] para i=2 hasta n-1. Debe observarse que el procedimiento recursivo permute emplea un parámetro valor. También cuando el número de objetos a permutar sea igual a uno, se trá una permutación lista para ser impresa. procedure permute(k:integer); var i : integer; if k=1 then salida else {se mantiene a[k] en su lugar} Prof. Leopoldo Silva Bijit. 07-07-2003 245

permute(k-1); {se generan las permutaciones de los k-1 objetos restantes} for i:=1 to k-1 do cambio de a[k] con a[i]; {pasos b y c} permute(k-1); se vuelve a[k] a posicion original; El siguiente programa permite generar permutaciones de caracteres. program permutaciones(input,output); {$A- Esta es una orden para el Compilador Turbo-Pascal} var n : integer; a : array[1..5] of char; procedure lea(var ch:char); read(kbd,ch) {lee sin eco; depe del compilador} procedure entrada; {llena arreglo de largo variable} var ch : char; write('->entre una secuencia de caracteres, terminada en punto: ') n:=0; lea(ch); while ch <> '.' do n:=n+1; a[n]:=ch; write(ch); lea(ch) writeln; procedure salida; var i : integer; for i:=1 to n do write(a[i]); Prof. Leopoldo Silva Bijit. 07-07-2003 246

writeln procedure permute(k:integer); procedure con_el_i_en_k; procedure cambio_k_por_i; var t : char; t:=a[i]; a[i]:=a[k]; a[k]:=t; {La llamada a permute (k-1) equivale a ir decrementando k} var i : integer; {con el i en k} for i:=1 to k-1 do cambio_k_por_i; permute(k-1); cambio_k_por_i {permute} if k=1 then salida else permute(k-1); {cona[k]fijo,genera las permutaciones de los k- 1 objetos precedentes.} con_el_i_en_k {repite con a[i] en el lugar de 1. } {principal} a[k], para i desde 1 a k- Permutaciones Entrada Salida Permute con_el_i_en_k Cambio Prof. Leopoldo Silva Bijit. 07-07-2003 247

entrada; permute(n). El diagrama anterior muestra la estructura de los bloques. SALIDA debe estar antes de PERMUTE, para ser accesible desde este último. CAMBIO es accesible sólo desde con_el_i_en_k. 19.3.2. Coeficientes Binomiales. Los coeficientes del binomio, suelen describirse por el triángulo de Pascal. 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1... Emplearemos la notación: Se tienen: n Cnk (, ) = k Prof. Leopoldo Silva Bijit. 07-07-2003 248

C(n,0) = 1 n >=0 C(n,k) = 0 n < k C(n,k) = C(n-1,k)+C(n-1,k-1) 0<=k<=n Las relaciones anteriores definen recursivamente al coeficiente del binomio; es inmediata entonces, la codificación: function C(n,k:integer):integer; if k=0 then C:=1 else if n<k then C:=0 else C:=C(n-1,k)+C(n-1,k-1) Pero también: Que puede escribirse: C(n,k) = n! / k!(n-k)! C(n,k) = (n-k+1)(n-k+2)..(n) / 1*2*3*..*k La siguiente función desarrolla el coeficiente binomial en forma no recursiva: function C(n,k:integer):integer; var num,den : integer; num:=1; den:=1; for j:=1 to k do num:=num*(n+1-j); den:=den*j C:=num div den Prof. Leopoldo Silva Bijit. 07-07-2003 249

19.3.3. Generador de Combinaciones. Analizar el algoritmo y colocar comentarios. program combinaciones(kbd,output); var m,n : integer; a : array[1..10] of integer; b : array[1..10] of char; procedure entrada; var ch : char; write('->entre secuencia de caracteres, terminada en punto: '); m:=0; read(kbd,ch); while ch <> '.' do m:=m+1; b[m]:=ch; write(ch); read(kbd,ch); a[m]:=m writeln; repeat write('->elementos de la combinacion: '); read(n); if n>m then write('<-error debe ser menor que: ',m+1); writeln until n<=m; procedure salida; var i : integer; writeln; for i:=1 to n do write(b[a[i]]) procedure combine; var p,b : integer; salida; {escribe la inicial} p:=1; while p<=n do Prof. Leopoldo Silva Bijit. 07-07-2003 250

if a[n+1-p] < m+1-p then b:=a[n+1-p]; while p>=1 do a[n+1-p]:=b+1; b:=b+1; p:=p-1 salida; p:=1 else p:=p+1 UNIVERSIDAD TECNICA FEDERICO SANTA MARIA writeln('generacion de combinaciones'); entrada; combine. Prof. Leopoldo Silva Bijit. 07-07-2003 251

19.3.4. Análisis sintáctico. UNIVERSIDAD TECNICA FEDERICO SANTA MARIA Se desea saber si una determinada secuencia de caracteres cumple las reglas sintácticas siguientes : <expresión> ::= <término>{'+' '-'<término>} <término> ::= <factor>{ '*' '/'<factor>} <factor> ::= <letra> '('<expresión> ')' '['<expresión>']' Nótese que <expresión> está definida en forma recursiva. Además se desea transformar la expresión a notación polaca inversa. Esta puede describirse por las siguientes reglas: t1 + t2 --> t1t2+ t1 - t2 --> t1t2- f1 * f2 --> f1f2* f1 / f2 --> f1f2/ (e) --> e [e] --> e Donde : t1 y t2 son términos; f1 y f2 son factores; y e es una expresión. Nótese que la secuencia de salida no contiene paréntesis. Se aprovecha el programa que permite recorrer la sintaxis para generar código; en este caso, se produce una secuencia en notación polaca inversa que podría posteriormente ser evaluada en una pila. En el programa se lee sin eco; se detectan errores de sintaxis, no aceptando caracteres ilegales, de acuerdo a las producciones. La secuencia de salida se almacena temporalmente en un arreglo; luego se la escribe en la misma línea que la secuencia aceptada de entrada. Se toman providencias para mantener alineadas las columnas de resultado, esto a través de una variable que contabiliza los pares de paréntesis. Prof. Leopoldo Silva Bijit. 07-07-2003 252

El programa ilustra el diseño de procedimientos locales. Factor es local a término; y término es local a expresión. En este caso, debe cuidarse la definición de las variables locales; ya que debido al carácter recursivo es necesario disponer de las encarnaciones adecuadas de las variables locales. Se emplea la técnica de leer un carácter por adelantado; y al mismo tiempo se valida que el carácter recién leído pertenezca al conjunto válido de caracteres siguientes. Nótese que el texto del programa refleja las producciones. La generación de la secuencia polaca inversa se logra, no pasando los paréntesis hacia el arreglo de salida; y posponio el paso de los operadores, hasta haber encontrado el siguiente factor o término. Se emplean conjuntos, los que son tratados en el capítulo siguiente. program polaca; const largo=20; var ch : char; salida : array[1..largo] of char; cursor : integer; cpar : integer; procedure leach; read(kbd,ch) {no estándar} procedure error; write(chr(07)); leach(ch) procedure wrt(ch : char); cursor:=cursor+1; salida[cursor]:=ch procedure wrtpol; var i : integer; for i:=1 to largo+10-cursor-cpar do write(' '); Prof. Leopoldo Silva Bijit. 07-07-2003 253

{compensa los parentesis con cpar} for i:=1 to cursor do write(salida[i]) procedure expresion; var sumop : char; procedure termino; var mulop : char; UNIVERSIDAD TECNICA FEDERICO SANTA MARIA procedure factor; {factor} if ch='(' then write(ch); leach(ch); while not (ch in ['a'..'z','(','[']) do error; expresion; while ch <> ')' do error; cpar:=cpar+2 else if ch='[' then write(ch); leach(ch);whilenot(ch in['a'..'z','(','['])do error; expresion; while ch <> ']' do error; cpar:=cpar+2 else while (ch<'a') or (ch>'z') do error; wrt(ch) write(ch); leach(ch); whilenot (ch in ['*','/','-','+',')',']','.']) do error; {factor} {termino} Prof. Leopoldo Silva Bijit. 07-07-2003 254

factor; while (ch='*') or (ch='/') do write(ch); mulop:=ch; leach(ch); while not (ch in ['a'..'z','(','[']) do error; factor; wrt(mulop) {termino} {expresion} termino; while (ch='+') or (ch='-') do write(ch); sumop:=ch; leach(ch); while not (ch in ['a'..'z','(','[']) do error; termino; wrt(sumop) {expresion} {polaca} clrsrc; {no estándar} writeln('entre <expresion>"." Y la paso a polaca inversa.'); write('->'); leach(ch); while not (ch in ['a'..'z','(','[','.']) do error; while ch <> '.' do cursor:=0; cpar:=0; expresion; wrtpol; writeln; write('->'); leach(ch);whilenot(ch in['a'..'z','(','[','.']) do error;. Prof. Leopoldo Silva Bijit. 07-07-2003 255