03.07.2013 Views

Recursie - caagt

Recursie - caagt

Recursie - caagt

SHOW MORE
SHOW LESS

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

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!