new fundamentos programación 2013 10 - academia cartagena99 · 2014. 7. 13. · la pila del...
TRANSCRIPT
23/05/2014
1
10
GradoenIngenieríaInformáticaGradoenIngenieríadelSoftware
GradoenIngenieríadeComputadores
LuisHernándezYáñez
FacultaddeInformáticaUniversidadComplutense
Fundamentos de la programación 2013‐2014
Luis Hernández Yáñez
Página 1Fundamentos de la programación: Introducción a la recursión
Concepto de recursión 2Algoritmos recursivos
Funciones recursivas 5Diseño de funciones recursivas 8
Modelo de ejecución 9La pila del sistema 10La pila y las llamadas a función 11Ejecución de la función factorial() 24
Tipos de recursiónRecursión simple 38recursión múltiple 39Recursión anidada 41Recursión cruzada 45
Código del subprograma recursivo 46Parámetros y recursión 51Ejemplos de algoritmos recursivos
Búsqueda binaria 54Torres de Hanoi 57
Recursión frente a iteración 62Estructuras de datos recursivas 64
23/05/2014
2
Luis Hernández Yáñez
Página 2Fundamentos de la programación: Introducción a la recursión
Luis Hernández Yáñez
Página 3Fundamentos de la programación: Introducción a la recursión
Recursión(recursividad,recurrencia)Sedicequealgosedefinedeformarecursivacuandoenladefiniciónapareceloqueseestádefiniendo.
Factorial(N)=Nx Factorial(N‐1) (N>0)
(wikipedia.org)(wikipedia.org)
Laimagendelpaqueteaparecedentrodelpropiopaquete,queasuvezcontieneotraimagendelpaquete...¡hastaelinfinito!
Laimagendelpaqueteaparecedentrodelpropiopaquete,queasuvezcontieneotraimagendelpaquete...¡hastaelinfinito!
(wikipedia.org)(wikipedia.org)
Cadatriánguloestáformadoporotros
triángulosmáspequeños.
Cadatriánguloestáformadoporotros
triángulosmáspequeños.
(http://farm1.static.flickr.com/83/229219543_edf740535b.jpg)
(http://farm1.static.flickr.com/83/229219543_edf740535b.jpg)
Lasmatrioskas rusasLasmatrioskas rusas
23/05/2014
3
Luis Hernández Yáñez
Página 4Fundamentos de la programación: Introducción a la recursión
RecursiónFactorial(N)=Nx Factorial(N‐1)
Elfactorialsedefineenfuncióndesímismo.
Losprogramasnopuedenmanejarlarecursióninfinita,quegeneraríaunbucleinfinitoenelprograma.
Ladefiniciónrecursivahadeiracompañadadeunoomáscasosbase.
Uncasobase esaquelenelquenoseutilizaladefiniciónrecursiva,sinoqueseproporcionaunpuntofinaldecálculo:
Cadavezqueseaplicaelcasorecursivo,elvalordeNsevaaproximandoalvalordelcasobase(0).
Nx Factorial(N‐1) siN>0 Casorecursivo(inducción)Factorial(N)=
1 siN=0 Casobase(odeparada)
Luis Hernández Yáñez
Página 5Fundamentos de la programación: Introducción a la recursión
23/05/2014
4
Luis Hernández Yáñez
Página 6Fundamentos de la programación: Introducción a la recursión
FuncionesrecursivasUnafunciónpuedeimplementarunalgoritmorecursivo:Lafunciónsellamaráasímismasinosehallegadoalcasobase.
long long int factorial(int n) {long long int resultado;if (n == 0) // Caso base
resultado = 1;else
resultado = n * factorial(n ‐ 1);
return resultado;}
Nx Factorial(N‐1) siN>0Factorial(N)=
1 siN=0
Luis Hernández Yáñez
Página 7Fundamentos de la programación: Introducción a la recursión
Funcionesrecursivaslong long int factorial(int n) {
long long int resultado;if (n == 0) // Caso base
resultado = 1;else
resultado = n * factorial(n ‐ 1);
return resultado;}
factorial(5) 5x factorial(4) 5x 4x factorial(3)
5x 4x 3x factorial(2) 5x 4x 3x 2x factorial(1)
5x 4x 3x 2x 1x factorial(0) 5x 4x 3x 2x 1x 1
120 CasobaseCasobase
factorial.cpp
23/05/2014
5
Luis Hernández Yáñez
Página 8Fundamentos de la programación: Introducción a la recursión
DiseñodefuncionesrecursivasUnafunciónrecursivadebesatisfacertrescondicionesparaestarbiendiseñada:
Caso(s)base:Debehaberalmenosuncasobasedeparada.
Inducción:Pasorecursivoqueprovocaunallamadarecursiva.Sepodrádemostrarqueescorrectoparadistintosparámetrosdeentrada.
Convergencia:Cadapasorecursivodebeacercarsealcasobase.
Describimoselproblemaentérminosdeproblemasmássencillos.
Lafunciónfactorial() tienecasobase(N=0),siendocorrectaparaNescorrectaparaN+1(inducción)yseacercacadavezmásalcasobase(N‐1estámáscercade0queN).
Nx Factorial(N‐1) siN>0Factorial(N)=
1 siN=0
Luis Hernández Yáñez
Página 9Fundamentos de la programación: Introducción a la recursión
23/05/2014
6
Luis Hernández Yáñez
Página 10Fundamentos de la programación: Introducción a la recursión
Modelodeejecuciónlong long int factorial(int n) {
long long int resultado;if (n == 0) // Caso base
resultado = 1;else
resultado = n * factorial(n ‐ 1);return resultado;
}
Cadallamadarecursivafuerzaunanuevaejecucióndelafunción,quedandointerrumpidalaactual.
Cadallamadaalafunciónutilizasuspropiosparámetrosporvaloryvariableslocales(n yresultado enestecaso).
Enlasllamadasalafunciónseutilizalapiladelsistemaparamantenerlosdatoslocalesyladireccióndevuelta.
Luis Hernández Yáñez
Página 11Fundamentos de la programación: Introducción a la recursión
Lapiladelsistema(stack)ElSOdisponeenlamemoriadelacomputadoravariasregionescondiferentespropósitos:
Pila (Stack)
Montón (Heap)
Datos del programa
Código del programa
S.O.
LlamadasafuncionesLlamadasafunciones
Memoriadinámica(Tema9)Memoriadinámica(Tema9)
MemoriaprincipalMemoriaprincipal
23/05/2014
7
Luis Hernández Yáñez
Página 12Fundamentos de la programación: Introducción a la recursión
Lapiladelsistema(stack)Lapilaseutilizaparaguardarencadallamadaafunciónlosdatoslocalesdelafunciónyladireccióndevuelta.
Esunaestructuradetipopila:listaLIFO(last‐infirst‐out)
Elúltimoqueentraeselprimeroquesale:
PilaPila
Entra4
Entra4
4
PilaPila
Entra7
Entra7
7
4
PilaPila
Entra2
Entra2
2
7
4
PilaPila
Sale2
Sale2
7
4
PilaPila
Luis Hernández Yáñez
Página 13Fundamentos de la programación: Introducción a la recursión
LapilaylasllamadasafunciónCadavezqueseproduceunallamadaaunafunciónsealojanenlapilasusdatoslocalesyladireccióndevuelta.
...int funcB(int x) {
...return x;
}
int funcA(int a) {int b;...b = funcB(a);... return b;
}
int main() {...cout << funcA(4);...
PilaPila<DIR1><DIR1>
<DIR2><DIR2>
Llamadaafunción:SeguardaladireccióndevueltaLlamadaafunción:Seguardaladireccióndevuelta
23/05/2014
8
Luis Hernández Yáñez
Página 14Fundamentos de la programación: Introducción a la recursión
LapilaylasllamadasafunciónCadavezqueseproduceunallamadaaunafunciónsealojanenlapilasusdatoslocalesyladireccióndevuelta.
...int funcB(int x) {
...return x;
}
int funcA(int a) {int b;...b = funcB(a);... return b;
}
int main() {...cout << funcA(4);...
<DIR1>
PilaPila<DIR1><DIR1>
<DIR2><DIR2>
Entradaenlafunción:SealojanlosdatoslocalesEntradaenlafunción:Sealojanlosdatoslocales
Luis Hernández Yáñez
Página 15Fundamentos de la programación: Introducción a la recursión
LapilaylasllamadasafunciónCadavezqueseproduceunallamadaaunafunciónsealojanenlapilasusdatoslocalesyladireccióndevuelta.
...int funcB(int x) {
...return x;
}
int funcA(int a) {int b;...b = funcB(a);... return b;
}
int main() {...cout << funcA(4);...
b
a
<DIR1>
PilaPila<DIR1><DIR1>
<DIR2><DIR2> Llamadaafunción:SeguardaladireccióndevueltaLlamadaafunción:Seguardaladireccióndevuelta
23/05/2014
9
Luis Hernández Yáñez
Página 16Fundamentos de la programación: Introducción a la recursión
LapilaylasllamadasafunciónCadavezqueseproduceunallamadaaunafunciónsealojanenlapilasusdatoslocalesyladireccióndevuelta.
...int funcB(int x) {
...return x;
}
int funcA(int a) {int b;...b = funcB(a);... return b;
}
int main() {...cout << funcA(4);...
<DIR2>
b
a
<DIR1>
PilaPila<DIR1><DIR1>
<DIR2><DIR2>
Entradaenlafunción:SealojanlosdatoslocalesEntradaenlafunción:Sealojanlosdatoslocales
Luis Hernández Yáñez
Página 17Fundamentos de la programación: Introducción a la recursión
LapilaylasllamadasafunciónCadavezquesevuelvedeunallamadaaunafunciónserecuperadelapilaladireccióndevueltadelafunciónanterior.
...int funcB(int x) {
...return x;
}
int funcA(int a) {int b;...b = funcB(a);... return b;
}
int main() {...cout << funcA(4);...
x
<DIR2>
b
a
<DIR1>
PilaPila<DIR1><DIR1>
<DIR2><DIR2>
Vueltadelafunción:SeeliminanlosdatoslocalesVueltadelafunción:Seeliminanlosdatoslocales
23/05/2014
10
Luis Hernández Yáñez
Página 18Fundamentos de la programación: Introducción a la recursión
LapilaylasllamadasafunciónCadavezquesevuelvedeunallamadaaunafunciónserecuperadelapilaladireccióndevueltadelafunciónanterior.
...int funcB(int x) {
...return x;
}
int funcA(int a) {int b;...b = funcB(a);... return b;
}
int main() {...cout << funcA(4);...
<DIR2>
b
a
<DIR1>
PilaPila<DIR1><DIR1>
<DIR2><DIR2>
Vueltadelafunción:SeobtieneladireccióndevueltaVueltadelafunción:Seobtieneladireccióndevuelta
Luis Hernández Yáñez
Página 19Fundamentos de la programación: Introducción a la recursión
LapilaylasllamadasafunciónCadavezquesevuelvedeunallamadaaunafunciónserecuperadelapilaladireccióndevueltadelafunciónanterior.
...int funcB(int x) {
...return x;
}
int funcA(int a) {int b;...b = funcB(a);... return b;
}
int main() {...cout << funcA(4);...
b
a
<DIR1>
PilaPila<DIR1><DIR1>
<DIR2><DIR2>LaejecucióncontinúaenesadirecciónLaejecucióncontinúaenesadirección
23/05/2014
11
Luis Hernández Yáñez
Página 20Fundamentos de la programación: Introducción a la recursión
LapilaylasllamadasafunciónCadavezquesevuelvedeunallamadaaunafunciónserecuperadelapilaladireccióndevueltadelafunciónanterior.
...int funcB(int x) {
...return x;
}
int funcA(int a) {int b;...b = funcB(a);... return b;
}
int main() {...cout << funcA(4);...
b
a
<DIR1>
PilaPila<DIR1><DIR1>
<DIR2><DIR2>
Vueltadelafunción:SeeliminanlosdatoslocalesVueltadelafunción:Seeliminanlosdatoslocales
Luis Hernández Yáñez
Página 21Fundamentos de la programación: Introducción a la recursión
LapilaylasllamadasafunciónCadavezquesevuelvedeunallamadaaunafunciónserecuperadelapilaladireccióndevueltadelafunciónanterior.
...int funcB(int x) {
...return x;
}
int funcA(int a) {int b;...b = funcB(a);... return b;
}
int main() {...cout << funcA(4);...
<DIR1>
PilaPila<DIR1><DIR1>
<DIR2><DIR2>
Vueltadelafunción:SeobtieneladireccióndevueltaVueltadelafunción:Seobtieneladireccióndevuelta
23/05/2014
12
Luis Hernández Yáñez
Página 22Fundamentos de la programación: Introducción a la recursión
LapilaylasllamadasafunciónCadavezquesevuelvedeunallamadaaunafunciónserecuperadelapilaladireccióndevueltadelafunciónanterior.
...int funcB(int x) {
...return x;
}
int funcA(int a) {int b;...b = funcB(a);... return b;
}
int main() {...cout << funcA(4);...
PilaPila<DIR1><DIR1>
<DIR2><DIR2>
LaejecucióncontinúaenesadirecciónLaejecucióncontinúaenesadirección
Luis Hernández Yáñez
Página 23Fundamentos de la programación: Introducción a la recursión
Mecanismodepilaadecuadoparallamadasafuncionesanidadas:
Lasllamadasterminanenelordencontrarioacomosellaman...int funcC(...) {...
}
int funcB(...) {...... funcC(...)
}
int funcA(...) {...... funcB(...)
}
int main() {...cout << funcA(...);...
funcC
funcB
funcA
PilaPila
LLAMADAS
LLAMADASV
UELTAS
VUELTAS
23/05/2014
13
Luis Hernández Yáñez
Página 24Fundamentos de la programación: Introducción a la recursión
Ejecucióndelafunciónfactorial()long long int factorial(int n) {
long long int resultado;if (n == 0) // Caso base
resultado = 1;else
resultado = n * factorial(n ‐ 1);
return resultado;}
Cadavezqueserealizaunallamadarecursivaseguardanenlapilalosdatoslocales(n yresultado)yladireccióndevuelta.
Veamoscómoseejecutafactorial(5),obviandolasdireccionesdevuelta,quesondatosdebajonivelynoafectanalaexplicación.
Luis Hernández Yáñez
Página 25Fundamentos de la programación: Introducción a la recursión
Ejecucióndelafunciónfactorial()factorial(5)
resultado = ?
n = 5
PilaPila
23/05/2014
14
Luis Hernández Yáñez
Página 26Fundamentos de la programación: Introducción a la recursión
Ejecucióndelafunciónfactorial()factorial(5)
factorial(4)
resultado = ?
n = 4
resultado = ?
n = 5
PilaPila
Luis Hernández Yáñez
Página 27Fundamentos de la programación: Introducción a la recursión
Ejecucióndelafunciónfactorial()factorial(5)
factorial(4)
factorial(3)
resultado = ?
n = 3
resultado = ?
n = 4
resultado = ?
n = 5
PilaPila
23/05/2014
15
Luis Hernández Yáñez
Página 28Fundamentos de la programación: Introducción a la recursión
Ejecucióndelafunciónfactorial()factorial(5)
factorial(4)
factorial(3)
factorial(2)
resultado = ?
n = 2
resultado = ?
n = 3
resultado = ?
n = 4
resultado = ?
n = 5
PilaPila
Luis Hernández Yáñez
Página 29Fundamentos de la programación: Introducción a la recursión
Ejecucióndelafunciónfactorial()factorial(5)
factorial(4)
factorial(3)
factorial(2)
factorial(1) resultado = ?
n = 1
resultado = ?
n = 2
resultado = ?
n = 3
resultado = ?
n = 4
resultado = ?
n = 5
PilaPila
23/05/2014
16
Luis Hernández Yáñez
Página 30Fundamentos de la programación: Introducción a la recursión
Ejecucióndelafunciónfactorial()factorial(5)
factorial(4)
factorial(3)
factorial(2)
factorial(1)
factorial(0)
resultado = 1
n = 0
resultado = ?
n = 1
resultado = ?
n = 2
resultado = ?
n = 3
resultado = ?
n = 4
resultado = ?
n = 5
PilaPila
Luis Hernández Yáñez
Página 31Fundamentos de la programación: Introducción a la recursión
Ejecucióndelafunciónfactorial()factorial(5)
factorial(4)
factorial(3)
factorial(2)
factorial(1)
factorial(0)
resultado = 1
n = 1
resultado = ?
n = 2
resultado = ?
n = 3
resultado = ?
n = 4
resultado = ?
n = 5
PilaPila
11
23/05/2014
17
Luis Hernández Yáñez
Página 32Fundamentos de la programación: Introducción a la recursión
Ejecucióndelafunciónfactorial()factorial(5)
factorial(4)
factorial(3)
factorial(2)
factorial(1)
factorial(0)resultado = 2
n = 2
resultado = ?
n = 3
resultado = ?
n = 4
resultado = ?
n = 5
PilaPila
11
11
Luis Hernández Yáñez
Página 33Fundamentos de la programación: Introducción a la recursión
Ejecucióndelafunciónfactorial()factorial(5)
factorial(4)
factorial(3)
factorial(2)
factorial(1)
factorial(0)
resultado = 6
n = 3
resultado = ?
n = 4
resultado = ?
n = 5
PilaPila
11
11
22
23/05/2014
18
Luis Hernández Yáñez
Página 34Fundamentos de la programación: Introducción a la recursión
Ejecucióndelafunciónfactorial()factorial(5)
factorial(4)
factorial(3)
factorial(2)
factorial(1)
factorial(0)
resultado = 24
n = 4
resultado = ?
n = 5
PilaPila
11
11
22
66
Luis Hernández Yáñez
Página 35Fundamentos de la programación: Introducción a la recursión
Ejecucióndelafunciónfactorial()factorial(5)
factorial(4)
factorial(3)
factorial(2)
factorial(1)
factorial(0)
resultado = 120
n = 5
PilaPila
11
11
22
66
2424
23/05/2014
19
Luis Hernández Yáñez
Página 36Fundamentos de la programación: Introducción a la recursión
Ejecucióndelafunciónfactorial()factorial(5)
factorial(4)
factorial(3)
factorial(2)
factorial(1)
factorial(0)
PilaPila
11
11
22
66
2424
120120
Luis Hernández Yáñez
Página 37Fundamentos de la programación: Introducción a la recursión
23/05/2014
20
Luis Hernández Yáñez
Página 38Fundamentos de la programación: Introducción a la recursión
RecursiónsimpleDecimosquelarecursiónessimplecuandoenlafunciónsólohayunallamadarecursiva.
Porejemplo,elcálculodelfactorialdeunnúmeroenteropositivo:
long long int factorial(int n) {long long int resultado;if (n == 0) // Caso base
resultado = 1;else
resultado = n * factorial(n ‐ 1);
return resultado;} UnallamadarecursivaUnallamadarecursiva
Luis Hernández Yáñez
Página 39Fundamentos de la programación: Introducción a la recursión
RecursiónmúltipleCuandoenlafunciónhayvariasllamadasrecursivasalapropiafunción,decimosquetenemosrecursiónmúltiple.
Porejemplo,elcálculodelosnúmerosdeFibonacci:
1 sin=1Fib(n)=
0 sin=0
Fib(n‐1)+Fib(n‐2) sin>1
DosllamadasrecursivasDosllamadasrecursivas
23/05/2014
21
Luis Hernández Yáñez
Página 40Fundamentos de la programación: Introducción a la recursión
Recursiónmúltiple:losnúmerosdeFibonacci...int fibonacci(int n) {
int resultado;if (n == 0)
resultado = 0;else if (n == 1)
resultado = 1;else
resultado = fibonacci(n ‐ 1) + fibonacci(n ‐ 2);
return resultado;}
int main() {for (int i = 0; i < 20; i++)
cout << fibonacci(i) << endl;
return 0;}
1 sin=1Fib(n)=
0 sin=0
Fib(n‐1)+Fib(n‐2) sin>1
fibonacci.cpp
Luis Hernández Yáñez
Página 41Fundamentos de la programación: Introducción a la recursión
RecursiónanidadaLarecursiónanidadalatenemoscuandoenunallamadarecursivaalgunodelosargumentosconsisteenotrallamadarecursiva.
Porejemplo,elcálculodelosnúmerosdeAckermann:
Ack(m‐1,1) sim>0yn=0Ack(m,n)=
n+1 sim=0
Ack(m‐1,Ack(m,n‐1)) sim>0yn>0
ArgumentoqueesunallamadarecursivaArgumentoqueesunallamadarecursiva
23/05/2014
22
Luis Hernández Yáñez
Página 42Fundamentos de la programación: Introducción a la recursión
Recursiónanidada:losnúmerosdeAckermann...int ackermann(int m, int n) {
int resultado;if (m == 0)
resultado = n + 1;else if (n == 0)
resultado = ackermann(m ‐ 1, 1);else
resultado = ackermann(m ‐ 1, ackermann(m, n ‐ 1));return resultado;
}
int main() {int m, n;cout << "M = "; cin >> m;cout << "N = "; cin >> n;cout << ackermann(m, n) << endl;return 0;
}
Ack(m‐1,1) sim>0yn=0Ack(m,n)=
n+1 sim=0
Ack(m‐1,Ack(m,n‐1)) sim>0yn>0
ackermann.cpp
Pruébaloconnúmerosmuybajos:
SegeneranMUCHASllamadasrecursivas
Luis Hernández Yáñez
Página 43Fundamentos de la programación: Introducción a la recursión
Recursiónanidada:losnúmerosdeAckermann
Ack(m‐1,1) sim>0yn=0
n+1 sim=0
Ack(m‐1,Ack(m,n‐1)) sim>0yn>022
33
ackermann(1, 1)
ackermann(0, ackermann(1, 0))
ackermann(0, 1)
ackermann(0, 2)
23/05/2014
23
Luis Hernández Yáñez
Página 44Fundamentos de la programación: Introducción a la recursión
Recursiónanidada:losnúmerosdeAckermann
Ack(m‐1,1) sim>0yn=0
n+1 sim=0
Ack(m‐1,Ack(m,n‐1)) sim>0yn>033
55
4455
ackermann(2, 1)
ackermann(1, ackermann(2, 0))
ackermann(1, 1)
ackermann(1, 3)
ackermann(0, ackermann(1, 2))
ackermann(0, ackermann(1, 1))
ackermann(0, 3)
ackermann(0, 4)
2233
ackermann(0, ackermann(1, 0))
ackermann(0, 1)
ackermann(0, 2)
2233
ackermann(0, ackermann(1, 0))
ackermann(0, 1)
ackermann(0, 2)
Luis Hernández Yáñez
Página 45Fundamentos de la programación: Introducción a la recursión
RecursióncruzadaoindirectaLarecursióncruzadaoindirectasedacuandounafunciónllamaaotrayéstaasuvezllamaalaprimera.Porejemplo,sabersiunnúmeroesparoimpar:bool par(int n) {
if (n == 0) return true;else return impar(n – 1);
}
bool impar(int n) {if (n == 0) return false;else return par(n – 1);
}
int main() {int x;cout << "Num: "; cin >> x;if (par(x)) cout << "Es par";else cout << "Es impar";...
par.cpp
23/05/2014
24
Luis Hernández Yáñez
Página 46Fundamentos de la programación: Introducción a la recursión
Luis Hernández Yáñez
Página 47Fundamentos de la programación: Introducción a la recursión
CódigoanterioryposterioralallamadarecursivaEngeneral,enunsubprogramarecursivotendremosuncódigoanterioralallamadarecursivayuncódigoposterior:
{CódigoanteriorLlamadarecursivaCódigoposterior
}
Elcódigoanterior seejecutarárepetidasvecesparalasdistintasentradasantesdequesellegueaejecutarcualquiercódigoposterior.Ésteseejecutarárepetidasvecesparalasdistintasentradastrasllegaralcasobase.Sinohaycódigoanterior,tenemosrecursiónpordelante.
Elcódigoanteriorseejecutaenordendirectoparalasdistintasentradas,mientrasqueelcódigoposteriorlohaceenordeninverso.Sinohaycódigoposterior,tenemosrecursiónpordetrás.
23/05/2014
25
Luis Hernández Yáñez
Página 48Fundamentos de la programación: Introducción a la recursión
Códigoanterioryposterioralallamadarecursivavoid func(int n) {
if (n > 0) {cout << "Entrando (" << n << ")" << endl; // Código anteriorfunc(n ‐ 1); // Llamada recursivacout << "Saliendo (" << n << ")" << endl; // Código posterior
}}
Sillamamosalafunciónconelargumento5,lasalidaserá:
Elcódigoanterioralallamadaseejecutaparalosdistintosvaloresquevatomandon.Elcódigoposterioralallamada,alrevés.
Luis Hernández Yáñez
Página 49Fundamentos de la programación: Introducción a la recursión
Recorridodeloselementosdeunalista(directo)Conelcódigoanterioralallamadaprocesamosloselementosenelmismoordenenqueseencuentran:...void mostrar(tLista lista, int pos);
int main() {tLista lista;lista.cont = 0;// Carga del array...mostrar(lista, 0);
return 0;}
void mostrar(tLista lista, int pos) {if (pos < lista.cont) {
cout << lista.elementos[pos] << endl;mostrar(lista, pos + 1);
}}
directo.cpp
23/05/2014
26
Luis Hernández Yáñez
Página 50Fundamentos de la programación: Introducción a la recursión
Recorridodeloselementosdeunalista(inverso)Conelcódigoposterioralallamadaprocesamosloselementosenelordeninversoenqueseencuentran:...void mostrar(tLista lista, int pos);
int main() {tLista lista;lista.cont = 0;// Carga del array...mostrar(lista, 0);
return 0;}
void mostrar(tLista lista, int pos) {if (pos < lista.cont) {
mostrar(lista, pos + 1);cout << lista.elementos[pos] << endl;
}}
inverso.cpp
Luis Hernández Yáñez
Página 51Fundamentos de la programación: Introducción a la recursión
23/05/2014
27
Luis Hernández Yáñez
Página 52Fundamentos de la programación: Introducción a la recursión
ParámetrosporvaloryporreferenciaEnlossubprogramasrecursivoslosparámetrosporvalorsondatosqueelsubprogramanecesitapararealizarsusoperaciones.(Encadallamadarecursivapuedenserdistintos.)Losparámetrosporreferenciasonresultadosquesevanconstruyendoalolargodelasdistintasllamadas(mismavariableenlasllamadas):
void factorial(int n, int &fact) {if (n == 0) fact = 1;else {
factorial(n ‐ 1, fact);fact = n * fact;
}}
Enlallamadaafactorial(0),fact tomaelvalor1.Alavuelta,selemultiplicaporeln delallamadaanterior(1).Yalavuelta,poreln delallamadaanterior(2).Yasísucesivamente...
Luis Hernández Yáñez
Página 53Fundamentos de la programación: Introducción a la recursión
23/05/2014
28
Luis Hernández Yáñez
Página 54Fundamentos de la programación: Introducción a la recursión
BúsquedabinariaLabúsquedabinariaesunejemplodealgoritmoquetrabajapartiendoelproblemaensubproblemasmáspequeñosyaplicandoelmismoprocesoacadasubproblema.
Esarepetición delprocesoparacadasubproblemamuestraunanaturalezarecursivaquenospermiteimplementarlaasí.Partimosdelalistacompletaenlaquehayquebuscar.Sinoquedalista...terminar(listavacía:noencontrado)Encasocontrario...
Comprobarsielelementoenlamitadeselbuscado.Sieselbuscado...terminar(encontrado).Sino...
Sielbuscadoesmenorqueelelementomitad...Quedarseconlaprimeramitaddelalistayrepetirelproceso
Sielbuscadoesmayorqueelelementomitad...Quedarseconlasegundamitaddelalistayrepetirelproceso
Luis Hernández Yáñez
Página 55Fundamentos de la programación: Introducción a la recursión
BúsquedabinariaAcadaejecucióndelafunciónselepasandosíndicesqueindiquenlasposicionesinicialyfinaldelasublistaaprocesardentrodelalista:
int buscar(tLista lista, int buscado, int ini, int fin)// Devuelve la posición donde está (0, ...) o ‐1 si no está
¿Cuálessonloscasosbase?
Queyanoquedesublista(ini > fin) Noencontrado
Queseencuentreelelemento
RepasacómofuncionaycómoseimplementólabúsquedabinariaenelTema7(implementacióniterativa).
23/05/2014
29
Luis Hernández Yáñez
Página 56Fundamentos de la programación: Introducción a la recursión
Búsquedabinaria
int buscar(tLista lista, int buscado, int ini, int fin) {int pos = ‐1;if (ini <= fin) {
int mitad = (ini + fin) / 2;if (buscado == lista.elementos[mitad])
pos = mitad;else
if (buscado < lista.elementos[mitad])pos = buscar(lista, buscado, ini, mitad ‐ 1);
elsepos = buscar(lista, buscado, mitad + 1, fin);
}return pos;
}
1ªllamada:pos = buscar(lista, buscado, 0, lista.cont ‐ 1);
binaria.cpp
Luis Hernández Yáñez
Página 57Fundamentos de la programación: Introducción a la recursión
Búsquedabinaria:implementaciónconparámetrosdesalida
void buscar(tLista lista, int buscado, int ini, int fin,bool & encontrado, int & pos) {
if (ini > fin) encontrado = false; else {
int mitad = (ini + fin) / 2;if (buscado == lista.elementos[mitad]) {
encontrado= true; pos = mitad;
}//ifelse {
if (buscado < lista.elementos[mitad])buscar(lista, buscado, ini, mitad ‐ 1, encontrado, pos);
elsebuscar(lista, buscado, mitad + 1, fin, encontrado, pos);
}//else}//else
}
1ªllamada:buscar(lista, buscado, 0, lista.cont ‐ 1, enc, i);
Pedro J. M
artín de la Calle
Pedro J. M
artín de la Calle
23/05/2014
30
Luis Hernández Yáñez
Página 58Fundamentos de la programación: Introducción a la recursión
LastorresdeHanoiCuentaunaleyendaqueenuntemplodeHanoisedispusierontrespilaresdediamanteyenunodeellos64discosdeoro,dedistintosradiosycolocadosporordendetamañoconelmayordebajo.
Cadamonje,ensuturno,debíamoverunúnicodiscodeunpilaraotro,deformaqueentretodosconsiganconeltiempollevarlatorredelpilarinicialaunodelosotrosdos.Debíanrespetarunaregla:nuncaponerundiscosobreotrodemenortamaño.Cuandolohayanconseguido,seacabaráelmundo.
[Serequierenalmenos264‐1movimientos;sisehicieraunoporsegundo,seterminaríaenmásde500milmillonesdeaños.]
Torredeochodiscos(wikipedia.org)Torredeochodiscos(wikipedia.org)
Luis Hernández Yáñez
Página 59Fundamentos de la programación: Introducción a la recursión
LastorresdeHanoiQueremosintentarresolvereljuego enelmenornúmerodemovimientosposible.
¿Quédiscohayquemoverencadapasoyadóndehayquemoverlo?
Primero,identifiquemosloselementos(torredecuatrodiscos):
Cadapilarseidentificaconunaletra.
MoverdelpilarXalpilarYsignificarácogereldiscosuperiordeXyponerloencimadelosquehayaenY.
AA BB CC
23/05/2014
31
Luis Hernández Yáñez
Página 60Fundamentos de la programación: Introducción a la recursión
LastorresdeHanoiDebemosenfocarlaresolucióndelproblemaenbaseaproblemasmáspequeños.
MoverNdiscosdelpilarAalpilarC:
MoverN‐1discosdelpilarAalpilarB
MovereldiscodelpilarAalpilarC
MoverN‐1discosdelpilarBalpilarC
ParallevarNdiscosdeunpilarorigenaotropilardestino seutilizaeltercerpilarcomoauxiliar:
MoverN‐1discosdelorigen alauxiliar
Movereldiscodelorigen aldestino
MoverN‐1discosdelauxiliar aldestino
AA BB CC
AA BB CC
AA BB CC
AA BB CC
Mover4discosdeAa CMover4discosdeAa C
Luis Hernández Yáñez
Página 61Fundamentos de la programación: Introducción a la recursión
LastorresdeHanoiMoverN‐1discosdeunpilaraotroserealizadelamismaforma,peroutilizandoahoraotrospilarescomoorigenydestino.
MoverN‐1discosdelpilarAalpilarB:
MoverN‐2discosdelpilarAalpilarC
MovereldiscodelpilarAalpilarB
MoverN‐2discosdelpilarCalpilarB
Claramentesepuederesolverfácilmenteconunaimplementaciónrecursiva.
AA BB CC
AA BB CC
AA BB CC
AA BB CC
Simulaciónpara4discos(wikipedia.org)Simulaciónpara4discos(wikipedia.org)
Mover3discosdeAa BMover3discosdeAa B
23/05/2014
32
Luis Hernández Yáñez
Página 62Fundamentos de la programación: Introducción a la recursión
LastorresdeHanoiCasobase:noquedandiscosquemover....void hanoi(int n, char origen, char destino, char auxiliar) {
if (n == 0) return;else {
hanoi(n ‐ 1, origen, auxiliar, destino);cout << origen << " ‐‐> " << destino << endl;hanoi(n ‐ 1, auxiliar, destino, origen);
}}
int main() {int n;cout << "N. torres: "; cin >> n;hanoi(n, 'A', 'B', 'C');
return 0;}
hanoi.cpp
Luis Hernández Yáñez
Página 63Fundamentos de la programación: Introducción a la recursión
23/05/2014
33
Luis Hernández Yáñez
Página 64Fundamentos de la programación: Introducción a la recursión
¿Quéespreferible?Cualquieralgoritmorecursivosepuedetraduciraunalgoritmoiterativoquerealiceelmismotrabajo.
Losalgoritmosrecursivossonmenoseficientesquesusalternativasiterativas:sobrecargadelasllamadasalossubprogramas.
Siemprequeresultesencillodesarrollarunaversióniterativa,éstaserápreferibleasuversiónrecursiva.
Peroenocasionesnoresultasencilloobteneresaversióniterativaequivalente,siendolaversiónrecursivamuchomássimple.Enestoscasosserápreferiblelaversiónrecursiva(sielrendimientonoesunfactorclave).
DesarrollaversionesiterativasdelfactorialodelosnúmerosdeFibonacci.¿YquétalconlosnúmerosdeAckermann?
Luis Hernández Yáñez
Página 65Fundamentos de la programación: Introducción a la recursión
23/05/2014
34
Luis Hernández Yáñez
Página 66Fundamentos de la programación: Introducción a la recursión
DefiniciónrecursivadelistasYahemosdefinidodeformarecursivaalgunaestructuradedatos:
Laslistastambiénsepuedendefinirdeformasimilar:
Lalista1,2,3consisteenelelemento1seguidodelalista2,3,que,asuvez,consisteenelelemento2seguidodelalista3,que,asuvez,consisteenelelemento3seguidodelalistavacía(casobase).Hayotrasestructurasconnaturalezarecursiva(comolosárboles)queestudiarásenposteriorescursos.
secuenciavacía(ningúnelemento)Secuencia=
elementoseguidodeunasecuencia
listavacía(ningúnelemento) (Casobase)Lista=
elementoseguidodeunalista
Luis Hernández Yáñez
Página 67Fundamentos de la programación: Introducción a la recursión
ProcesamientodeestructurasrecursivasLanaturalezarecursivadealgunasestructurasdedatosllevadeformanaturalaunprocesamientorecursivodelasmismas:
Procesar(lista):
Silistanovacía(casobase):
Procesarelprimerelementodelalista//Códigoanterior
Procesar(resto(lista))
Procesarelprimerelementodelalista//Códigoposterior
Donderesto(lista) devuelveunalistaigualalaqueseproporcionasinsuprimerelemento.
23/05/2014
35
Luis Hernández Yáñez
C++:An Introduction to Computing (2ªedición)J.Adams,S.Leestma,L.Nyhoff.Prentice Hall,1998
EllenguajedeprogramaciónC++ (Ediciónespecial)B.Stroustrup.Addison‐Wesley,2002
ProgramaciónenC++paraingenierosF.Xhafa etal.Thomson,2006
Fundamentos de la programación: Introducción a la recursión Página 68
Luis Hernández Yáñez
LicenciaCC(Creative Commons)Estetipodelicenciasofrecenalgunosderechosaterceraspersonasbajociertascondiciones.
Estedocumentotieneestablecidaslassiguientes:
Pulsaenlaimagendearribaaladerechaparasabermás.
Fundamentos de la programación: Introducción a la recursión Página 69
Reconocimiento(Attribution):Encualquierexplotacióndelaobraautorizadaporlalicenciaharáfaltareconocerlaautoría.
Nocomercial(Noncommercial):Laexplotacióndelaobraquedalimitadaausosnocomerciales.
Compartirigual(Sharealike):Laexplotaciónautorizadaincluyelacreacióndeobrasderivadassiemprequemantenganlamismalicenciaalserdivulgadas.