Recursie - caagt
Recursie - caagt
Recursie - caagt
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
<strong>Recursie</strong><br />
Ontwerp van recursieve algoritmen<br />
Analyse van recursieve algoritmen<br />
Wanneer recursie af te raden is<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.1/42
Faculteit berekenen<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.2/42
Berekenen van faculteit<br />
Wiskundige definitie van faculteit<br />
n! = n × (n − 1)!<br />
1! = 1<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.3/42
Berekenen van faculteit<br />
Wiskundige definitie van faculteit<br />
n! = n × (n − 1)!<br />
1! = 1<br />
Opstellen van recursief algoritme<br />
om n! te berekenen: n! = n × (n − 1)!<br />
bereken (n − 1)!, vermenigvuldig dit met n<br />
berekening van (n − 1)! is een analoog,<br />
eenvoudiger probleem<br />
speciaal geval is hier: 1! = 1<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.3/42
Implementatie<br />
Implementatie recursief algoritme<br />
long faculteit ( int n ) { //ond. n>=1<br />
}<br />
if ( n==1) return 1;<br />
else return n ∗ faculteit ( n−1);<br />
Oproepen van methode<br />
void doeIets ( int n ) {<br />
}<br />
long f = faculteit ( n ) ;<br />
// doe iets met waarde van f<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.4/42
Ontwerp van recursieve<br />
algoritmen<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.5/42
<strong>Recursie</strong>ve algoritmen<br />
Wat is recursie?<br />
methode kan in zijn blok een oproep naar<br />
zichzelf bevatten, d.i. recursieve oproep<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.6/42
<strong>Recursie</strong>ve algoritmen<br />
Wat is recursie?<br />
methode kan in zijn blok een oproep naar<br />
zichzelf bevatten, d.i. recursieve oproep<br />
Principe van recursie<br />
probleem wordt opgesplitst in deelproblemen<br />
deelproblemen zijn analoog, maar “kleiner”<br />
eenvoudiger varianten van zelfde probleem<br />
totdat triviaal geval bekomen wordt<br />
speciaal eindgeval, afbreekpunt recursie<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.6/42
Test 1<br />
Output van methode?<br />
void doeIets ( ) {<br />
}<br />
doeIets ( 3 ) ;<br />
void doeIets ( int n ) {<br />
if ( n
Test 2<br />
Output van methode?<br />
void doeIets ( ) {<br />
}<br />
doeIets ( 3 ) ;<br />
void doeIets ( int n ) {<br />
if ( n
Programmeertechniek recursie<br />
Ontwerp van een recursief algoritme<br />
bedenken of/hoe probleem op te splitsen in<br />
analoge, kleinere deelproblemen<br />
bepalen van speciaal geval, afbreekpunt<br />
implementeren in recursieve methode<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.9/42
Programmeertechniek recursie<br />
Ontwerp van een recursief algoritme<br />
bedenken of/hoe probleem op te splitsen in<br />
analoge, kleinere deelproblemen<br />
bepalen van speciaal geval, afbreekpunt<br />
implementeren in recursieve methode<br />
Opmerkingen<br />
“systeem” zorgt voor goede afhandeling van<br />
recursieve oproep<br />
m.a.w. mogen veronderstellen dat recursieve<br />
oproep gewenste resultaat geeft<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.9/42
Torens van Hanoi<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.10/42
Torens van Hanoi<br />
Probleem<br />
geg. toren van schijven op staaf<br />
alle schijven hebben verschillende grootte<br />
grootste onderaan, andere in volgorde<br />
gevr. toren overbrengen naar andere staaf<br />
slechts één schijf per keer verplaatsen<br />
nooit grotere schijf op kleinere plaatsen<br />
derde staaf als hulpstaaf gebruiken<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.11/42
Torens van Hanoi<br />
Probleem<br />
geg. toren van schijven op staaf<br />
alle schijven hebben verschillende grootte<br />
grootste onderaan, andere in volgorde<br />
gevr. toren overbrengen naar andere staaf<br />
slechts één schijf per keer verplaatsen<br />
nooit grotere schijf op kleinere plaatsen<br />
derde staaf als hulpstaaf gebruiken<br />
Oplossing (zie animatie, Java-applet)<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.11/42
<strong>Recursie</strong>f algoritme<br />
Algemeen geval (n > 1)<br />
verplaatsen van toren van n schijven<br />
verplaats toren van n − 1 schijven van<br />
beginstaaf naar hulpstaaf<br />
verplaats onderste schijf van beginstaaf<br />
naar eindstaaf<br />
verplaats toren van n − 1 schijven van<br />
hulpstaaf naar eindstaaf<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.12/42
<strong>Recursie</strong>f algoritme<br />
Algemeen geval (n > 1)<br />
verplaatsen van toren van n schijven<br />
verplaats toren van n − 1 schijven van<br />
beginstaaf naar hulpstaaf<br />
verplaats onderste schijf van beginstaaf<br />
naar eindstaaf<br />
verplaats toren van n − 1 schijven van<br />
hulpstaaf naar eindstaaf<br />
Speciaal geval (n = 1)<br />
toren bestaande uit 1 schijf<br />
d.i. verplaatsen van 1 schijf<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.12/42
Implementatie<br />
<strong>Recursie</strong>ve methode<br />
void hanoi ( int n , int start ,<br />
if ( n==1)<br />
int doel , int hulp ) {<br />
schijf ( n , start , doel ) ;<br />
else {<br />
}<br />
hanoi ( n−1,start , hulp , doel ) ;<br />
schijf ( n , start , doel ) ;<br />
hanoi ( n−1,hulp , doel , start ) ;<br />
} Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.13/42
Machtsverheffing<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.14/42
Machtsverheffing<br />
Probleem<br />
berekenen van x n , voor x ∈ R en n ∈ N<br />
Steunen op definitie<br />
x n = x × · · · × x<br />
<br />
n keer<br />
iteratief algoritme (met for-lus)<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.15/42
Machtsverheffing<br />
Probleem<br />
berekenen van x n , voor x ∈ R en n ∈ N<br />
Steunen op definitie<br />
x n = x × · · · × x<br />
<br />
n keer<br />
iteratief algoritme (met for-lus)<br />
Basisidee voor recursief algoritme<br />
x n = x × x n−1 , voor n > 0<br />
x 0 = 1<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.15/42
Implementatie<br />
Java-code<br />
double macht ( double x , int n ) {<br />
}<br />
// onderstel n>=0<br />
if ( n==0)<br />
else<br />
return 1;<br />
return x ∗ macht ( x , n−1);<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.16/42
Ander algoritme?<br />
Beter idee?<br />
steunen op<br />
x n = (x 2 ) n/2 , voor n > 0 even<br />
x n = (x 2 ) (n−1)/2 × x, voor n > 0 oneven<br />
x 0 = 1<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.17/42
Implementatie<br />
Java-code tweede algoritme<br />
double macht ( double x , int n ) {<br />
}<br />
// onderstel n>=0<br />
if ( n==0)<br />
return 1;<br />
else if ( n%2==0)<br />
else<br />
return macht ( x∗x , n / 2 ) ;<br />
return macht ( x∗x , n / 2 ) ∗ x ;<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.18/42
Staartrecursie<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.19/42
Staartrecursie<br />
Opmerking<br />
recursie is krachtige ontwerptechniek<br />
maar in sommige situaties te vermijden<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.20/42
Staartrecursie<br />
Opmerking<br />
recursie is krachtige ontwerptechniek<br />
maar in sommige situaties te vermijden<br />
Staartrecursie<br />
recursie die eigenlijk eenvoudige for-lus<br />
vervangt<br />
wanneer na recursieve oproep niets meer<br />
gebeurt<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.20/42
Voorbeeld: ggd<br />
Berekenen van grootste gemene deler<br />
zij n ≥ m > 0 natuurlijke getallen<br />
eigenschap: ggd(n,m) = ggd(m,nmod m)<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.21/42
Voorbeeld: ggd<br />
Berekenen van grootste gemene deler<br />
zij n ≥ m > 0 natuurlijke getallen<br />
eigenschap: ggd(n,m) = ggd(m,nmod m)<br />
herhaaldelijk toepassen tot n modm = 0<br />
leidt tot algoritme van Euclides<br />
er geldt: ggd(n, 0) = n<br />
Voorbeeld<br />
ggd(144, 84) = ggd(84, 60) = ggd(60, 24) =<br />
ggd(24, 12) = ggd(12, 0) = 12<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.21/42
Implementatie<br />
<strong>Recursie</strong>ve implementatie<br />
int ggd ( int n , int m ) { // ond. n>=m<br />
}<br />
Merk op<br />
if ( m == 0) return n ;<br />
else return ggd ( m , n % m ) ;<br />
na recursieve oproep gebeurt niets meer<br />
m.a.w. staartrecursie<br />
gemakkelijk te vervangen door iteratie (lus)<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.22/42
Niet-recursieve implementatie<br />
int ggd ( int n , int m ) { // ond. n>=m<br />
}<br />
while ( m != 0) {<br />
}<br />
int hlp = m ; m = n % m ; n = hlp ;<br />
return n ;<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.23/42
Binaire zoekmethode<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.24/42
Binaire zoekmethode<br />
Probleem<br />
zoeken van getal in gesorteerde rij<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.25/42
Binaire zoekmethode<br />
Probleem<br />
zoeken van getal in gesorteerde rij<br />
Basisidee<br />
vergelijk gezochte getal met element in het<br />
midden<br />
met één vergelijking de helft van de rij<br />
elimineren<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.25/42
Algoritme<br />
1: if getal < eerste of > laatste element then<br />
2: getal komt niet voor in rij<br />
3: else if rij bestaat uit één element then<br />
4: controleer of getal gelijk aan dit element<br />
5: else<br />
6: vergelijk getal met middelste element uit rij<br />
7: if kleiner then<br />
8: verderzoeken in linkerhelft<br />
9: else if groter then<br />
10: verderzoeken in rechterhelft<br />
11: else<br />
12: gevonden<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.26/42
Implementatie<br />
boolean binarySearch ( int [ ] a ,<br />
int van , int tot , int x ) {<br />
if ( van==tot ) return x==a [ van ] ;<br />
if ( xa [ tot ] ) return false ;<br />
int midden = ( van+tot ) / 2 ;<br />
if ( xa [ midden ] )<br />
return binarySearch ( a , midden+1 ,tot , x ) ;<br />
else return true ;<br />
} Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.27/42
oolean binarySearch ( int [ ] a , int x ) {<br />
}<br />
return binarySearch ( a , 0 , a . length−1,x ) ;<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.28/42
Analyse van recursieve<br />
algoritmen<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.29/42
Analyse van recursieve algoritmen<br />
Uitvoeringstijd van recursief algoritme<br />
beschreven in recurrente betrekking<br />
Technieken voor oplossen van recurrente<br />
betrekkingen<br />
substitutiemethode<br />
iteratiemethode<br />
master-methode<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.30/42
Berekenen van faculteit<br />
Implementatie recursief algoritme<br />
long faculteit ( int n ) { // ond. n>=1<br />
}<br />
if ( n==1) return 1;<br />
else return n ∗ faculteit ( n−1);<br />
Uitvoeringstijd recursief algoritme<br />
bepaald door recurrente betrekking<br />
T(1) = Θ(1)<br />
T(n) = T(n − 1) + Θ(1) (voor n > 1)<br />
in gesloten uitdrukking? Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.31/42
Iteratiemethode<br />
Iteratiemethode<br />
omzetten van recursie naar sommatie<br />
begrenzen van sommaties, recursiebomen<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.32/42
Iteratiemethode<br />
Iteratiemethode<br />
omzetten van recursie naar sommatie<br />
begrenzen van sommaties, recursiebomen<br />
Voorbeeld (cfr. berekenen faculteit)<br />
recurrente betrekking<br />
T(1) = 1<br />
T(n) = T(n − 1) + 1 (voor n > 1)<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.32/42
Iteratiemethode<br />
Iteratiemethode<br />
omzetten van recursie naar sommatie<br />
begrenzen van sommaties, recursiebomen<br />
Voorbeeld (cfr. berekenen faculteit)<br />
recurrente betrekking<br />
T(1) = 1<br />
T(n) = T(n − 1) + 1 (voor n > 1)<br />
oplossing<br />
T(n) = n<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.32/42
Torens van Hanoi<br />
Uitvoeringstijd<br />
bepaald door recurrente betrekking<br />
T(1) = Θ(1)<br />
T(n) = 2T(n − 1) + Θ(1) (voor n > 1)<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.33/42
Torens van Hanoi<br />
Uitvoeringstijd<br />
bepaald door recurrente betrekking<br />
T(1) = Θ(1)<br />
T(n) = 2T(n − 1) + Θ(1) (voor n > 1)<br />
Oplossen<br />
via iteratiemethode (als oefening)<br />
via substitutiemethode<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.33/42
Substitutiemethode<br />
Substitutiemethode<br />
schatten van (begrenzing voor) oplossing<br />
bewijzen door wiskundige inductie<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.34/42
Substitutiemethode<br />
Substitutiemethode<br />
schatten van (begrenzing voor) oplossing<br />
bewijzen door wiskundige inductie<br />
Voorbeeld (cfr. torens van Hanoi)<br />
recurrente betrekking<br />
T(1) = 1<br />
T(n) = 2T(n − 1) + 1 (voor n > 1)<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.34/42
Substitutiemethode<br />
Substitutiemethode<br />
schatten van (begrenzing voor) oplossing<br />
bewijzen door wiskundige inductie<br />
Voorbeeld (cfr. torens van Hanoi)<br />
recurrente betrekking<br />
T(1) = 1<br />
T(n) = 2T(n − 1) + 1 (voor n > 1)<br />
oplossing<br />
T(n) = 2 n − 1<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.34/42
Master-methode<br />
Recept voor oplossen recurrenties<br />
T(n) = a × T(n/b) + f(n)<br />
voor constanten a ≥ 1, b > 1<br />
voor asymptotisch positieve functie f(n)<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.35/42
Master-methode<br />
Recept voor oplossen recurrenties<br />
T(n) = a × T(n/b) + f(n)<br />
voor constanten a ≥ 1, b > 1<br />
voor asymptotisch positieve functie f(n)<br />
Beschrijft verdeel-en-heers algoritme<br />
probleem van grootte n wordt opgesplitst in<br />
a deelproblemen van grootte n/b<br />
elk deelprobleem wordt opgelost in T(n/b)<br />
kost van opsplitsen en samenvoegen<br />
deelresultaten beschreven door f(n)<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.35/42
Machtsverheffing / Binaire zoekm.<br />
Uitvoeringstijd<br />
bepaald door recurrente betrekking<br />
T(1) = Θ(1)<br />
T(n) = T(n/2) + Θ(1) (voor n > 1)<br />
in gesloten uitdrukking?<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.36/42
Master-stelling<br />
Zij T(n) = aT(n/b) + f(n), met a ≥ 1 en b > 1<br />
constanten, f(n) asymptotisch positieve functie.<br />
Dan T(n) als volgt asymptotisch te begrenzen:<br />
1. als f(n) = O(n log b a−ǫ ) voor zekere cte. ǫ > 0,<br />
dan T(n) = Θ(n log b a )<br />
2. als f(n) = Θ(n log b a ), dan<br />
T(n) = Θ(n log b a log n)<br />
3. als f(n) = Ω(n log b a+ǫ ) voor zekere cte. ǫ > 0,<br />
als af(n/b) ≤ cf(n) voor zekere cte. c < 1 en<br />
voldoende grote n, dan T(n) = Θ(f(n))<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.37/42
Voorbeeld 1<br />
Recurrente betrekking: T(n) = T(n/2) + Θ(1)<br />
a = 1, b = 2, log b a = 0, n log b a = 1<br />
te vergelijken met f(n) = Θ(1)<br />
dus f(n) = Θ(n log b a )<br />
geval 2 van de master-stelling<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.38/42
Voorbeeld 1<br />
Recurrente betrekking: T(n) = T(n/2) + Θ(1)<br />
a = 1, b = 2, log b a = 0, n log b a = 1<br />
te vergelijken met f(n) = Θ(1)<br />
dus f(n) = Θ(n log b a )<br />
geval 2 van de master-stelling<br />
Oplossing<br />
T(n) = Θ(log n)<br />
Dus: binaire zoekmethode en machtsverheffing<br />
zijn Θ(log n) algoritmen<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.38/42
Voorbeeld 2<br />
Recurrente betrekking: T(n) = 2T(n/2) + Θ(n)<br />
a = 2, b = 2, log b a = 1, n log b a = n<br />
te vergelijken met f(n) = Θ(n)<br />
dus f(n) = Θ(n log b a )<br />
geval 2 van de master-stelling<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.39/42
Voorbeeld 2<br />
Recurrente betrekking: T(n) = 2T(n/2) + Θ(n)<br />
a = 2, b = 2, log b a = 1, n log b a = n<br />
te vergelijken met f(n) = Θ(n)<br />
dus f(n) = Θ(n log b a )<br />
geval 2 van de master-stelling<br />
Oplossing<br />
T(n) = Θ(n log n)<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.39/42
Berekenen van<br />
Fibonacci-getallen<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.40/42
Fibonacci-getallen<br />
Definitie<br />
F0 = 0,F1 = 1<br />
Fn = Fn−1 + Fn−2, voor n > 1<br />
Naïeve recursieve implementatie<br />
long fibo ( int n ) { //ond. n>=0<br />
}<br />
if ( n
Complexiteit fibo(n)<br />
Recurrente betrekking<br />
T(0) = Θ(1), T(1) = Θ(1)<br />
T(n) = T(n − 1) + T(n − 2) + Θ(1)<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.42/42
Complexiteit fibo(n)<br />
Recurrente betrekking<br />
T(0) = Θ(1), T(1) = Θ(1)<br />
T(n) = T(n − 1) + T(n − 2) + Θ(1)<br />
Oplossing<br />
T(n) ≥ Fn<br />
er geldt: Fn ≥ (3/2) n−2<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.42/42
Complexiteit fibo(n)<br />
Recurrente betrekking<br />
T(0) = Θ(1), T(1) = Θ(1)<br />
T(n) = T(n − 1) + T(n − 2) + Θ(1)<br />
Oplossing<br />
Dus<br />
T(n) ≥ Fn<br />
er geldt: Fn ≥ (3/2) n−2<br />
algoritme met exponentiële uitvoeringstijd<br />
cfr. niet-recursief Θ(n) algoritme!<br />
Cursus Algoritmen en Datastructuren voor Geomatica (2008–2009) – p.42/42