STRUKTURIERTES [height=4ex]img/javalogo PROGRAMMIEREN ·...
-
Upload
nguyendung -
Category
Documents
-
view
214 -
download
0
Transcript of STRUKTURIERTES [height=4ex]img/javalogo PROGRAMMIEREN ·...
STRUKTURIERTES PROGRAMMIEREN
Vorlesung im Sommersemester 2014
Prof. E.G. Schukat-Talamazzini
Stand: 15. Oktober 2014
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Teil VIII
Rekursion
Maurits Cornelis Escher: Zeichnen (1948)
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Mathematische InduktionGaußsche Summationsformel
σ(N)def=
N∑i=1
i = 1 + 2 + 3 + . . .+ N =N2· (N + 1)
Induktionsbeweis1. Induktionsanfang: σ(1) = 1 = 1/2 · (1+ 1)
2. Induktionsvoraussetzung: σ(N − 1) = (N−1)/2 · N
3. Induktionsschritt:σ(N) = σ(N − 1) + N = (N−1)/2 · N + N
= (N+1)/2 · N = N/2 · (N + 1)
Rekursionsformel für die Reihe arithmetischer Summen
σ(N)def=
{1 N = 1σ(N − 1) + N N > 1
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Was ist Rekursion ?
Rekursiv formulierte AlgorithmenEine Funktion f ruft sich bei Berechnung selbst auf.
• direkter oder indirekter Selbstaufruf ?
• Aufruf einfacherer Inkarnationen ihrer selbst
• EffektivitätTerminierung · Zyklen · endloser Abstieg ?
• EffizienzBerechnungsaufwand Aufrufverzweigung
Beispiele rekursiver AlgorithmenZählen aller Bytes in den Dateien eines KatalogbaumsNachschlagen einer Bedeutung im WörterbuchArithmetische Ausdrücke in BNF-Notation
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Rekursion und IterationBeispiel — rekursive Summenberechnungint sigmaRec(int n) {
return (n==0) ? 0 : // Trivialfall(sigmaRec(n-1) + n) ; // Selbstaufruf
}
Beispiel — induktive Summenberechnungint sigmaInd(int n) {
int[] sig = new int[1+n]; // Zwischenergebnissesig[0] = 0; // Trivialfallfor (int i=1; i<=n; i++) // Traversieren
sig[i] = sig[i-1] + i; // Gedächtnisabrufreturn sig[n];
}
Kompaktvariante (Speicherüberlagerung für Zwischenresultate)int sig = 0;for (int i=1; i<=n; i++) sig = sig + i;return sig;
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Beispiele rekursiver Funktionsdeklarationenin Java-ähnlicher Notation
Ganzzahlige Addition und Multiplikationint add (int n, int m)
{ return (n == 0) ? m : succ (add (n-1,m)); }
int mult (int n, int m){ return (n == 0) ? 0 : add (mult (n-1,m), m); }
Ganzzahlige Division und Restint div (int n, int m)
{ return (n < m) ? 0 : div (n-m,m) + 1; }
int mod (int n, int m){ return (n < m) ? n : mod (n-m,m); }
Binomialkoeffizientenint binom (int n, int m) {
return (m == 0 || m == n) ? 1 :binom (n-1,m-1) + binom (n-1,m);
}
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Beispiele rekursiver Funktionsdeklarationen(Fortsetzung)
Palindromeigenschaftint zpot (int n)
{ return (n < 10) ? 1 : zpot (n/10) * 10; }
int spiegel (int n) {return (n < 10) ? n :
n%10 * zpot (n) + spiegel (n/10);}
boolean palindrom (int n){ return (n == spiegel (n)); }
Spiegelung von Dezimalziffern
4 7 1 1 4 7 1 1 471 1 1 471 1 1 7 4
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Rekursionsformen
Effizienz
Entwurfstechniken
Teile & Herrsche
Dynamische Programmierung
Backtracking (Trial & Error)
Sortieren
Zusammenfassung
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Rekursionsformen IKetten- oder baumförmige Aufrufhierarchie
fak(4)
fak(3)
fak(2)
fak(1)
fak(0)
linear
bifak(1,5)
bifak(1,3) bifak(4,5)
bifak(2,2)bifak(1,1)
bifak(1,2) bifak(5,5)bifak(3,3) bifak(4,4)
kaskadiert
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Rekursionsformen II
ack(3,3)
ack(2,?) ack(3,2)
ack(3,0)
ack(2,?)
ack(2,?)
ack(2,1)
ack(2,0)ack(1,?)
ack(1,0)ack(0,?)
ack(1,1)
ack(0,1)
ack(3,1)
verschachtelt
dynamische Schachtelung
wechselseitiger Aufruf
q2odd(LOLLO)
q2odd(LOLL)
q2even(LOL)
q2odd(LO)
q2odd(L)
verschränkt
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Lineare Rekursion
STECKBRIEFLaufzeit Aufruf provoziert ≤ 1 UnteraufrufeSyntax ≤ 1 F -Auftreten je BedingungszweigAufwand Aufrufkette lineares WachstumBeispiele div, fac, ggT, sqrt
Beispiel - Fakultätsfunktionint factorial (int n)
{ return (n == 0) ? 1 : n * factorial (n-1); }
Aufrufdiagrammfac(5) r*5
fac(4) r*4
fac(3) r*3
fac(2) r*2
fac(1)←1
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Beispiele — lineare Rekursion
Größter gemeinsamer Teilerint ggT (int n, int m) {
return (n == m) ? n :(n < m) ? ggT (n, m-n) :
ggT (n-m, m) ;}
Der Funktionsbezeichnerdarf durchaus mehrfachim Rumpf auftreten,allerdings maximal 1× jeZweig einerFallunterscheidung.
Quadratwurzel durch Intervallschachtelungdouble sqrt (double x, double a, double b) {
final double Z = (b-a) / 2;return (b-a < 1e-24) ? Z :
(Z*Z < x) ? sqrt (x, Z, b) :sqrt (x, a, Z) ;
}
Das initialeAufrufintervall[a, b] muß dierichtige Lösung√
x mitSicherheitenthalten.
Aufrufausdruck: (x>1) ? sqrt(x,1,x) : sqrt(x,x,1)
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Kaskadierte RekursionSTECKBRIEFLaufzeit Aufruf provoziert evt. auch > 1 UnteraufrufeSyntax ex. Bedingungszweig mit ≥ 2 F -AuftretenAufwand Aufrufbaum u.U. exponentielles WachstumBeispiele fib, bifac, Kansas City, Quicksort
Beispiel - Fibonaccizahlenint fib (int n) {
return (n == 0) ? 1 :(n == 1) ? 1 : fib (n-2) + fib (n-1) ;
}
Aufrufdiagrammfib(3) ⊕ 1+ 2
fib(1)←1fib(2) ⊕ 1+ 1
fib(0)←1 fib(1)←1
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Beispiele — kaskadierte Rekursion
Fakultät durch Bisektionint bifac (int m, int n) {
return (m > n) ? 1 :(m == n) ? n :
bifac (m, (m+n)/2) * bifac ((m+n)/2 + 1, n) ;}
Aufruf:fac(n) ≡ bifac(1,n)
Optimale Wege in Kansas-Cityint kansas (int i, int j, int m, int n) {
return (i == m) ? 1 :(j == n) ? 1 : kansas (i+1,j,m,n) + kansas (i,j+1,m,n) ;
}Iterierte Quersummenberechnungint quer (int n) {
return (n < 10) ? n : x%10 + quer (x/10) ;}int iquer (int n) {
return (n < 10) ? n : iquer (quer (n)) ;}
Achtung!nichtgeschachteltnichtverschränktnicht einmalkaskadiert
Optimale Wege in der L1-MetrikIn der Reißbrettstadt Wolfsburg (oder Kansas City) verlaufen alle Straßen äquidistantund kartesisch, d.h. genau Ost-West oder Nord-Süd.
d(x , y) = ‖x − y‖1def= |x1 − y1|+ |x2 − y2|
Die Kreuzungen seien mit ganzzahligen Koordinaten (i , j) ∈ Z× Z bezeichnet.Kürzeste Wege von (0, 0) nach (n,m) vermeiden konsequent jeglichen Umweg inRichtung Süd oder West; ihre Länge ist also stets n + m.
Analytische LösungFür die auf kürzesten Wegen zu bewältigenden Streckenelemente (n× Nord und m×Ost) gibt es (n + m)! mögliche Reihenfolgen, von denen aber wegen der inhärentenUnunterscheidbarkeit der Nord- und der Ostelemente nur
wolfsburg(n,m) =(n + m)!
n! ·m!=(n + m
n
)zu berücksichtigen sind.
Rekursive LösungVon (0, 0) nach (10, 10) gibt es 184.756 Minimalwege. Die kaskadierte Rekursionbenötigt zur Berechnung dieses Resultats stattliche 369.511 Funktionsaufrufe,beginnend mit kansas(0,0,10,10).
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Verschachtelte RekursionSTECKBRIEFLaufzeit auch die F -Argumente werden durch F -Aufrufe berechnetSyntax extrem diffizile TerminierungsbeweiseAufwand unter Umständen hyperexponentielles WachstumBeispiele ackermann
Beispiel - die Ackermannfunktionint acker (int m, int n) {
return (m == 0) ? (n+1) :(n == 0) ? acker (m-1, 1) :
acker (m-1, acker (m, n-1)) ;}Einige Funktionswerte
m/n 0 1 2 3 4 5 60 1 2 3 4 5 6 71 2 3 4 5 6 7 82 3 5 7 9 11 13 153 5 13 29 61 125 253 5094 13 ?? . . . . . .5 ?? . . . . . . . . .
Anzahl Selbstaufrufem/n 0 1 2 3 4 5 60 1 1 1 1 1 1 11 2 4 6 8 10 12 142 5 14 27 44 65 90 1193 15 106 541 2432 10307 42438 1722334 107 ?? (> 5 · 106)5 ?? . . .
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Wissenswertes über die AckermannfunktionInduktiv definierte arithmetische VerknüpfungenUnendliche Folge zweistelliger Rechenoperationen:
g1(n,m)def= n +m = (n + (m − 1)) + 1
g2(n,m)def= n ·m = (n · (m − 1)) + n
g3(n,m)def= nm =
(nm−1) · n
g4(n,m)def= n ◦m = (n ◦ (m − 1))n
g5(n,m)def= n ♦m = (n ♦ (m − 1)) ◦ n
. . . . . . . . .
gk(n,m)def= gk−1(gk(n,m − 1), n) (∀k ∈ IN)
DiagonalenprojektionWir beschränken unser Interesse auf Berechnungen mit gleichen Operandenn = m, also n + n, n · n, nn, n ◦ n, n ♦ n, usw.:
ackermann(k, n) def= gk(n, n) für alle k, n ∈ IN
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Verschränkte Rekursion
Zyklus wechselseitiger AufrufeSystem von KFunktionsdeklarationenIndirekter Selbstaufruf „über Bande“Typisch für OO-Programmierung
f1 ← f2 ← . . . ← f`−1
↓ ↑fK f`↓ ↑
fK−1 → fK−2 → . . . → f`+1
Beispiel - Test auf un/gerade Quersummeboolean q2odd (int n) {
return ( n == 0) ? false :(n%2 == 0) ? q2odd (n/2) :
q2even (n/2) ;}boolean q2even (int n) {
return ( n == 0) ? true :(n%2 == 0) ? q2even (n/2) :
q2odd (n/2) ;}
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Schlichte Rekursion (Endrekursion)
STECKBRIEFSpezialfall der linearen RekursionLaufzeit Selbstaufruf ist die „letzte Amtshandlung“ im RumpfSyntax F -Aufruf = äußere Schale im KlammergebirgeAufwand wie lineare Rekursion; ggf. speicherfreundlichBeispiele mod, ggT, sqrt, iquer, divauxGegenbeispiele add, mult, div, fac, kaskadierte Deklarationen
Aufrufdiagramm für die ggT-DeklarationggT(21,33) r
ggT(21,12) r
ggT(9,12) r
ggT(9,3) r
ggT(6,3) r
ggT(3,3)←3
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Beispiel — eine schlichte Variante der DivisionDivision mit Hilfsargumentint divaux (int n, int m, int h) {
return (n < m) ? h: divaux (n-m, m, h+1) ;
}
Semantische ÄquivalenzEin divaux(n,m,0) -Aufruf berechnet den Ganzzahlquotienten, denn:
divaux (n,m,h) ≡ div (n,m) + h
Beweis.• Induktionsanfang: Ist n < m, so gilt div(n,m)≡ n/m = 0.
Der Aufruf divaux(n,m,h) liefert dann aber auch h = 0+ h.
• Induktionsschluß:divaux(n,m,h) ≡ divaux(n-m,m,h+1)
I .V .≡ div(n-m,m) + (h+1)
≡ div(n,m) + h
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Endrekursion und Iteration
EndrekursionSchema für einen Parameter
T f (T ′ x) {return B(x) ?
f (φ(x)) :ψ(x) ;
}
IterationSemantisch gleichwertig:
T f (T ′ x) {while (B(x))
x = φ(x);return ψ(x);
}
Trivialschalter B, Problemreduktion φ, Trivialrechnung ψ
Aufrufschema für die Endrekursionf (x) r
f (φ(x)) r
f (φ2(x)) r
f (φ3(x)) r
ψ(φ3(x))
Eingespart Rechenzeit⊕ Speicher
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Zwischenbilanz
Mathematische Funktion implementierte FunktionDie Rekursionsform ist eine Eigenschaft derFunktionsdeklaration, nicht aber der mathematischen Funktionper se.• Die ganzzahlige Division ist in unseren Beispielen einmal linear(div) und einmal schlicht (divaux) deklariert.
• Die Fakultätsfunktion ist einmal linear (fac) und einmalkaskadiert (bifac) deklariert.
EinbettungstechnikSystematische Methode zurVerschönerung der Rekursionsform
scheinbar N.R.
kaskadiertlinear
schlicht(iterativ)
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Einbettung mit ZusatzargumentenAufgabe ohne kanonisch-rekursive Formulierungprim(n)
?≡ Ψ( n, prim(n-1), prim(n-2), . . .)
zusätzliche
Parameter
EINBETTUNG
Problemstellung Verallgemeinerung
Spezialfall
Einbettungstechnik
1. Hilfsargumente einführen f (x) g(h, x)
2. Rekursiv formulieren g(h, x) ≡ Ψ(x , h, g(h′, x ′), g(h′′, x ′′), . . .)
3. per Treibermethode aufrufen f (x) ≡ g(h∗, x)
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Beispiel — Rekursion um jeden Preis(scheinbar nicht rekursiv schlicht)
GrundideeEine Zahl n ∈ IN ist prim n besitzt keinen Teiler in [2, n/2]
Teilerrekursion für den Primzahltest
boolean teilerBis (int h, int n) {return (h < 2) ? false :
(n%h == 0) ? true :teilerBis (h-1, n) ;
}
Treibermethode für den Primzahltest
boolean prim (int n) {return (n > 1) && ! teilerBis (n/2, n) ;
}
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Beispiel — Fakultät für schlichte Informatik(linear schlicht)
Rekursion für Fakultät
int sfac (int h, int n) {return (n == 0) ?
h :sfac (h*n, n-1) ;
}
Treibermethode für Fakultät
int sfac (int n) {return sfac (1, n);
}
(überladene Methodennamen!)
GrundideeStatt n! auf n · (n − 1)! zu reduzieren,berechne sukzessive Produkte derForm n · (n − 1) · . . . · (m + 1) ·m;Weiterleitung via h an denUnteraufruf.
Invariantesfac(h, n) = h · n!
Beweis.Vollständige Induktion:Für n = 0 liefert sfac(1,n) dasArgument h = 1 ab und für n > 0 gilt:
sfac(h, n) = sfac(h · n, n − 1)I .V .= h · n · (n − 1)!
= h · n!
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Beispiel — Fibonacci goes schlicht(kaskadiert schlicht)
Rekursion für Fibonacci
int sfib (int r, int q, int k) {return (k == 0) ?
q : (k == 1) ?r :sfib (r+q, r, k-1) ;
}
Treibermethode für Fibonacci
int sfib (int n) {return sfib (1,1,n);
}
(überladene Methodennamen!)
GrundideeHilfsparameter für Fn−1 und Fn−2
InvarianteNach Aufruf sfib(1, 1, n) gilt stets=β [(r , q, k)] = (Fn−k+1,Fn−k , k)
Beweis.Es gilt die Äquivalenzkette
sfib(n) ≡ sfib(1, 1, n)
≡ sfib(F1,F0, n)
≡ sfib(F2,F1, n − 1)
≡ sfib(F3,F2, n − 2)
≡ . . .
≡ sfib(Fn−1,Fn−2, 2)
≡ sfib(Fn,Fn−1, 1)
≡ Fn
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Rekursionsformen
Effizienz
Entwurfstechniken
Teile & Herrsche
Dynamische Programmierung
Backtracking (Trial & Error)
Sortieren
Zusammenfassung
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Entwurf rekursiver Algorithmen(Küchlin & Weber, Kapitel 10.1)
AlgorithmenschemaBestandteile des Deklarationsrumpfes einer rekursiven Funktion
1 Initialisierungen final int FAC0 = 1;Deklaration & Definition von Variablen und Konstanten
2 Ausnahmefälle if (n<0) throw new Except...();Prüfen der Vorbedingungen
3 Trivial- oder Basisfälle if (n==0) return FAC0;Induktionsanfang: Direktberechnung
4 Reduktion int sub1 = n-1;auf „einfachere“ Teilaufgaben
5 Rekursion int res1 = fac (sub1);durch Unteraufruf(e) der Funktion selbst
6 Rekombination return n * res1;der erzielten Zwischenresultate
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Korrekte, terminierende & effiziente Rekursion4+1 goldene Regeln rekursiver Programmierung (M.A. Weiss)
• es gibt mindestens einen direkt lösbaren Fall• Unteraufrufe Fortschritt in Richtung Trivialfall• alle Unteraufrufe sind generell erfolgreich• keine unnötige Berechnung von Zwischenergebnissen• keine vermeidbaren Anfängerfehler
Berechnung der Binomialkoeffizienten(nk
)=
n!k! · (n − k)!
=
{ n/k ·(n−1k−1
)k > 0
1 k = 0
Warum ist das folgende Programmfragment keine gute Idee ?
int binom (int n, int k) {return (k == 0) ? 1 : n/k * binom (n-1, k-1) ;
}
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Die Effizienz eines Algorithmus
Papierverbrauch: Schreibtischfläche:Wieviele Blätter werden Wieviele Blätter werdeninsgesamt benötigt ? gleichzeitig verwendet ?RECHENAUFWAND SPEICHERBEDARF
PapierbogenmetapherU.-Aufruf =̂ neues BlattResultat zerknüllen
DefinitionFür eine Funktionsdeklaration
T0 f (T1 n, ...) { SRumpf }
mit einem formalen Parameter n ganzzahligen Typs definieren wir diefolgenden Effizienzmaße:1. Aufrufbreite Φb
f (n) Gesamtzahl aller ausgeführten f -Aufrufe
2. Aufruftiefe Φtf (n) Max. Anzahl gleichzeitig aktiver f -Aufrufe
3. Rechenaufwand Φrf (n) Gesamtzahl auszuwertender Grundoperationen
4. Speicherbedarf Φsf (n) Max. Anzahl simultaner Identifikatorbindungen
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Beispiel — Effizenzberechnung
Ganzzahlige Divisionsmethode
int div (int n, int m){ return (n < m) ? 0 : div (n-m,m) + 1; }
AufruftiefeΦt
div(n,m) = n/m + 1
Der (kettenförmige) Aufrufbaumbesitzt n/m innere Knoten und einenBlattknoten (ohne Unteraufruf).
AufrufbreiteΦb
div(n,m) = n/m + 1
In jedem der n/m + 1 Aufrufe schlagendie beiden lokalen Variablen n und m zuBuche.
SpeicherbedarfΦs
div(n,m) = 2 · n/m + 2
In jedem Aufruf sind drei arithmetischeOperationen auszuführen: derGrößenvergleich n<m, die Subtraktionn-m und die Addition div()+1.
RechenaufwandΦr
div(n,m) = 3 · n/m + 1
Im Blattaufruf entfallen die beidenletzten Operationen.
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Rechenaufwand und Programmlaufzeit
Beispielprozedur(geschachtelte Laufschleifen)
void proz (int n){proz_1();proz_1();for (int i=1; i<=n; i++){
proz_2();proz_2();proz_2();for (int j=1; j<=n; j++){
proz_3();proz_3();
}}
}
Laufzeit in Sekundenproz_1 proz_2 proz_3
Rechner A 3 s 5 s 4 sRechner B 5 s 3 s 7 sRechner C 17 s 14 s 23 sallgemein ζ1 s ζ2 s ζ3 s
Anzahl Operationen=β [n] 1 10 100 1000 nproz_1 2 2 2 2 2proz_2 3 30 300 3000 3nproz_3 2 200 20000 2000000 2n2
Asymptotisches VerhaltenWelches ist der dominierende Term für n→∞ ?
Φz(n)Φz(m)
=2n2ζ3 + 3nζ2 + 2ζ12m2ζ3 + 3mζ2 + 2ζ1
≈ 2n2ζ32m2ζ3
=( nm
)2
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Die Landau-SymbolikDefinitionEs seien g : IN→ IN und φ : IN→ IN zwei Abbildungen. Wir schreiben
g(n) = O(φ(n)) (g(·) ist ein Groß-„Oh!“ von φ(·)),
wenn es zwei positive reelle Zahlen c1, c2 gibt und ein n0 ∈ IN mit
n ≥ n0 ⇒ c1 ≤g(n)
φ(n)≤ c2 ,
d.h., g(·) wächst in der gleichen Größenordnung wie φ(·).
Beispielkomplexitäten:
• Φb(n) = 17 O(1) bzw. O(n0)
• Φb(n) = 2n + 5 O(n) bzw. O(n1)
• Φb(n) = 2n2 + 3n + 2 O(n2)
• Φb(n) = n3 + 883n2 O(n3)
• Φb(n) = n log2(n) + 12n O(n log n)
• Φb(n) = 2n + 17n8 O(2n)
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Asymptotik gängiger Komplexitätsklassenkonstant · logarithmisch · linear · polynomial · exponentiell
1
10
100
1000
10000
2 4 6 8 10 12 14 16 18
Kom
plex
itaet
Parameter ’n’
2*x**0log(x)
x**1x*log(x)
x**210*x**2
x**32**x
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Terminierung rekursiver FunktionenO(∞) — die scheußlichste aller Komplexitätsklassen
FaktMethodenaufruf terminiert endliche Zahl von Selbstaufrufen
MotivationFür die Aufrufbreite des kaskadierten Algorithmus zur Berechnung derFibonacci-Zahlen gilt
Φbfib(n) =
{1 n ∈ {0, 1}Fn+1 + Fn−2 − 1 n ≥ 2 ;
dabei sei {Fn}n∈IN die Fibonacci-Reihe.Insbesondere terminiert der Algorithmus für alle Eingaben n ∈ IN.
Fibonaccizahlen und ihre Aufruftiefe
n 0 1 2 3 4 5 6 7 8 9 10 11 ...Fn 1 1 2 3 5 8 13 21 34 55 89 144 ...Φb
fib(n) 1 1 3 5 9 15 25 41 67 109 177 287 ...
Beweis.Für n ≥ 2 gehorcht die Aufrufbreite der Rekursionsformel
Φbfib(n) = 1+Φb
fib(n − 1) +Φbfib(n − 2)
• Induktionsanfang.Für n ∈ {0, 1} ergibt sich die Aussage aus der Tabelle und für n ∈ {2, 3}gilt:
Φbfib(2) = 3 = 3+ 1− 1 = F3 − F0 − 1
Φbfib(3) = 5 = 5+ 1− 1 = F4 − F1 − 1
• Induktionsschritt.Und nun der Schluß von n − 2 und n − 1 auf n:
Φbfib(n) = Φb
fib(n − 2) +Φbfib(n − 1) + 1
= (Fn−1 + Fn−4 − 1) + (Fn + Fn−3 − 1) + 1
= (Fn−1 + Fn) + (Fn−4 + Fn−3) + (1− 1− 1)
= Fn+1 + Fn−2 − 1
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Terminierungsbeweise
DefinitionEine Funktion ϕ : IN→ IR heißt Majorante für die Aufrufbreite von f ,wenn sie eine obere Schranke für die Anzahl rekursiver f -Aufrufe darstellt:
∀n ∈ IN : Φbf (n) ≤ ϕf (n)
Direkter BeweisBerechne die Funktion Φb
f (n)
⊕ Induktionsbeweis simpel
Formel finden schwierig
Indirekter BeweisFinde (irgendeine) geeigneteMajorante ϕf (n) von Φb
f (n)
⊕ Induktionsbeweis simpel
⊕ Schranke durch Probieren
Beispiel FibonaccizahlenΦb
fib(n) ≤ ϕfib(n)def= 2n
Beweis.• Induktionsanfang.
Die drei ersten Fälle:
20 ≥ 1
21 ≥ 1
22 ≥ 3
• Induktionsschritt.Ab n = 3 verfängt der Induktionsschritt
Φbfib(n) = Φb
fib(n − 2) +Φbfib(n − 1) + 1
≤ 1+ 2n−2 + 2n−1
≤ 2n−2 + 2n−2 + 2n−1
= 1/4 · 2n + 1/4 · 2n + 1/2 · 2n
= 2n
●
●
●
●
●
●
●
●
●
●
●
0 2 4 6 8 10
15
1050
100
500
1000
n
loga
rithm
isch
e S
kala
● ●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
Majorante 2^nAufruftiefeFibonaccizahlen
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Rekursionsformen
Effizienz
Entwurfstechniken
Teile & Herrsche
Dynamische Programmierung
Backtracking (Trial & Error)
Sortieren
Zusammenfassung
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Klassische Entwurfstechnikenam Beispiel der Berechnung power(x,n) = xn
AufwandΦ(f(n)) = Φ(Overhead) + Φ(U-Aufrufe)
Dekomposition⊗ eindeutig zerlegbar ?⊗ gleicher Gesamtaufwand ?⊗ gleiches Zwischenergebnis ?
Zwischenergebnisse⊗ dopppelt gemoppelt⊗ überflüssig
Gierige Algorithmenwählen (erst-)beste Zerlegung
Vorbedingungen abprüfen
Trivialfälle direkt ausrechnen
Zerlegung der Aufgabenstellung
f(n¹) f(n²) f(n³) f(...)
Zusammenführung der Teilergebnisse
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Gierige Algorithmen„greedy“ oder „gefräßig“
SteckbriefDie Aufgabe wird in sehr ungleiche Teile zerlegt; höchstens eineTeilaufgabe ist nicht trivial.
• ignoriert Zerlegungsvarianten u.U. suboptimales Ergebnis
• lineare Rekursion i.A. günstige Laufzeit
Im Beispiel beträgt die Aufrufbreite ΦbpowerGR(n) = n + 1.
double powerGR (double x, int n) {return (n == 0) ? 1
: x * powerGR (x, n-1) ;}
x9
x8
x7
x6
x5
x4
x3
x2
x1
x0
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Teile und Herrsche („divide & conquer“)SteckbriefDie Aufgabe wird in mindestens einem Fall in ≥ 2 Teile zerlegt.
• kaskadierte Rekursion parallelisierbar?
• kombinatorische Explosion exponentieller Aufwand ?
Im Beispiel beträgt die Aufrufbreite im günstigsten Fall — wenn nZweierpotenz ist — Φb
powerGR(n) = 2n − 1.
double powerDC (double x, int n) {return (n == 0) ? 1 :
(n == 1) ? x :powerDC (x, n/2) * powerDC (x, n - n/2);
}
x9
x4
x5
x2
x2
x2
x3
x1
x1
x1
x1
x1
x1
x1
x2
x1
x1
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Dynamische ProgrammierungSteckbriefLösung von Teilaufgaben & Tabellierung und Abruf der Ergebnisse
• Teilaufgaben überschneiden — Zerlegung uneindeutig
• Gedächtnis statt Mehrfachberechnung
• Iteration (Speicher füllen) statt Rekursion
Im Beispiel beträgt die Aufrufbreite ΦbpowerDP(n) = O(n).
double powerDP (double x, int n) {double[] r = new double [n+1];r[0] = 1; r[1] = x;for (int i = 1; i <= n; i++) r[i] = r[i/2] * r[i - i/2];return r[n];
}
x9
x8
x7
x6
x5
x4
x3
x2
x1
x0
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Backtracking oder „trial & error“SteckbriefPulsierendes Berechnen der Zwischenergebnisse bei Bedarf („JIT“)
• nicht alle Teilaufgaben sind zu lösen
• Zerlegungen uneindeutig — konkurrierende Berechnungspfade
Im Beispiel beträgt die Aufrufbreite ΦbpowerBT(n) = O(log2(n)).
double powerBT (double x, int n, double[] r) {if (n == 0) r[0] = 1;else if (n == 1) r[1] = x;else { if (r[n/2]==0) r[n/2] = powerBT (n/2);
if (r[n-n/2]==0) r[n-n/2] = powerBT (n-n/2);r[n] = r[n/2] * r[n - n/2];
}return r[n];
}
x9
x5
x4
x3
x2
x1
x0
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Überraschungserfolgkaskadiert linear schlicht iterativ
double powerCas (double x, int n) {return (n==0) ? 1 :
(n%2==1) ? x * powerCas(x,n-1) :powerCas(x,n/2) *powerCas(x,n/2);
}
Kaskadiertxn =
1 n = 0x · x2m n = 2m + 1xm · xm n = 2m
double powerLin (double x, int n) {if (n==0) return 1;if (n%2==1) return x * powerLin(x,n-1);final double USETWICE = powerLin(x,n/2);return USETWICE * USETWICE;
}
Linearxn =
1 n = 0x · x2m n = 2m + 1(xm)2 n = 2m
double powerLoop (double x, int n) {double reval = 1;while (n>0)
if (n%2==1) { reval *= x; n -= 1; }else { x *= x; n /= 2; }
return reval;}
Schlicht & iterativSchleifeninvariante:reval* x*x*...*x︸ ︷︷ ︸
n-mal
= const
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Rekursionsformen
Effizienz
Entwurfstechniken
Teile & Herrsche
Dynamische Programmierung
Backtracking (Trial & Error)
Sortieren
Zusammenfassung
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Beispiel — die maximale TeilsummeMCSSS = „maximum contiguous subsequence sum“
Taggenaue Kurse eines AktienfondsWelche Kombination aus An- und Verkaufdatum ist die rentabelste?Kalendertag 1 2 3 4 5 6 7 8 9 10Gewinn/Verlust +5 −8 +3 +3 −5 +7 −2 −7 +3 +5
Lösung:acht Euro Gewinn bei Kauf vor dem 3. Juli und Verflüssigung nach dem 6. Juli
DefinitionEs sei x = 〈x1, . . . , xn〉 eine reellwertige Zahlenfolge. Der Wert
MCS3(x)def= max
1≤j,k≤nSj,k(x) mit Sj,k(x)
def=
k∑i=j
xi
heißt maximale Teilsumme von x .
(Konvention: die leere Teilsumme ist Null)
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Ein kubischer MCS3-AlgorithmusExplizite Berechnung/Vergleich aller Teilsummenmit drei geschachtelten Zählschleifen:
double mcsss3 (double[] x) { //double smax = 0.0; // leere Teilfolgefor (int j = 0; j < x.length; j++) // Anfangsindex
for (int k = j; k < x.length; k++) { // Endeindexdouble summe = 0.0; //for (int i = j; i <= k; i++) // Summationsschleife
summe += x[i]; //if (summe > smax) // Maximumbildung
smax = summe; //} //
return smax; //}
ZeitkomplexitätDie innerste Anweisung summe+=x[i]; wird im Fall n≡ x.length genau1/6n3 + 1/2n2 + 1/3n1 = O(n3) mal ausgeführt.
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Ein quadratischer MCS3-AlgorithmusGewinne Zeit — spendiere SpeicherStatt alle Teilfolgensummen getrennt zu berechnen, werden Summen längererFolgen auf Summen kürzerer Folgen zurückgeführt.
Sj,k(x) =
{xj j = kSj,k−1(x) + xk j < k
Kumulative Teilsummenberechnungmit (2×) zwei geschachtelten Zählschleifen: Rechenaufwand O(n2)double mcsss2 (double[] x) {
final int N = x.length;double[][] su = new double [N][N]; // nur superdiagonalfor (int j = 0; j < N; j++) { // Anfangsindex
su[j][j] = x[j]; // Induktionsanfangfor (int k = j+1; k < N; k++) // Endeindex
su[j][k] = su[j][k-1] + x[k]; // Induktionsschritt}double smax = 0.0;for (int j = 0; j < N; j++)
for (int k = j; k < N; k++) smax = Math.max (su[j][k], smax);return smax;
}
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Ein linearer MCS3-AlgorithmusEinbettung mit Zusatzziel — der „hat trick“Rekursionsgleichung für die beste mit xk endende Teilsumme:
Rk(x)def= max
jSj,k(x) =
{0 k = 0max(0,Rk−1(x) + xk) k > 0
Integrierte Summation und Doppelmaximierungmit einer einzigen Zählschleife: Rechenaufwand O(n1)
double mcsss1 (double[] x) {double smax = 0.0; // MCSSS in x[0:i]double rmax = 0.0; // Max. Summe x[?:i]for (int i = 0; i < x.length; i++) {
rmax = Math.max (0, rmax + x[i]); // innere Maximierungsmax = Math.max (smax, rmax); // äußere Maximierung
}return smax;
}
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Divide & Conquer
Problemreduktion
• Maximale Teilsumme in⟨x1, . . . , xn/2
⟩ rekursiver Aufruf #1
• Maximale Teilsumme, Berechnung mitdie xn/2 und xn/2+1 enthält Aufwand O(n1)
• Maximale Teilsumme in⟨xn/2+1, . . . , xn
⟩ rekursiver Aufruf #2
Exemplarische Zerlegung 〈x1, . . . , x5〉 ◦ 〈x6, . . . , x10〉Kalendertag 1 2 3 4 5 6 7 8 9 10Gewinn/Verlust +5 −8 +3 +3 −5 +7 −2 −7 +3 +5∑← /
∑→ −2 −7 +1 −2 −5 +7 +5 −2 +1 +6
je Aufruf zwei „halbschwere“ UnteraufrufeBestimmung der „grenzüberschreitenden“ MCS3
Aufrufbaum mit circa log2 n Ebenenje Ebene querbeet O(n) Operationen
RechenaufwandO(n · log2 n)
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Ein kaskadierter MCS3-Algorithmusdouble mcsssDC (double[] x) { // Treibermethode
return mcsss (x, 0, x.length-1);}double mcsss (double[] x, int l, int r) { // Einbettmethode
if (l == r)return Math.max (0, x[l]); // Trivialfall
final int m = (l+r)/2; // die "Neue Mitte"final double mcsl = mcsss (x, l, m); // 1. Unteraufruffinal double mcsr = mcsss (x, m+1, r); // 2. Unteraufruffinal double mcsm = mcsGoLeft (x, m, l) // <----| max.Summe
+ mcsGoRight (x, m+1, r); // dto. |---->return Math.max (mcsm, Math.max (mcsl, mcsr)); // Rekombination
}double mcsGoLeft (double[] x, int m, int l) {
double reval = 0.0; // die max. Summefor (double sum = 0.0; m >= l; sum += x[m--]) // alle Teilsummen
if (sum > reval) reval = sum;return reval;
}double mcsGoRight (double[] x, int m, int r) {...} // s.o. fohrwerz
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Algorithmen mit geometrischer Reduktion
SatzEs sei f ein D&C-Algorithmus mit derCharakteristik
Φbf (n) = α ·Φb
f (n/β) + O(nk)
und α ≥ 1, β > 1. Dann besitzt f die folgendeWachstumsordnung:
Φbf (n) =
O(nlogβ α) α > βk
O(nk log n) α = βk
O(nk) α < βk
Fertilität αWievieleTeilaufgaben?
Skalierung βWelcher Verein-fachungsfaktor?
Overhead kWas kostenReduktion undRekombinati-on?(k-polynomial)
Overhead O(nk)
{ Reduktion
f1 f2 f3 · · · fα{ Rekombination
fi (n/β)
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Beispiele — Rechenaufwand von D&C-AlgorithmenMaximale Teilsumme
ΦbmcsssDC(n) = 2 ·Φb
mcsssDC(n/2) + O(n1) = O(n1 log n)
Potenzberechnung
ΦbpowerDC(n) = 2 ·Φb
powerDC(n/2) + O(n0) = O(nlog2 2) = O(n1)
Drei halbe Aufrufe & linearer Overhead
Φbf (n) = 3 ·Φb
f (n/2) + O(n1) = O(nlog2 3) = O(n1.59)
Drei halbe Aufrufe & quadratischer Overhead
Φbf (n) = 3 ·Φb
f (n/2) + O(n2) = O(n2)
Fibonaccizahlen, Fakultätsfunktion ??
β 6> 1
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Algorithmen mit arithmetischer ReduktionSatzEs sei f ein D&C-Algorithmus mit derVerzweigungscharakteristik
Φbf (n) =
k∑`=1
α` ·Φbf (n − β`) n ≥ maxβ`
1 n < maxβ`
mit k ∈ IN und β1, . . . , βk ∈ IN. Dann gilt für dieAnzahl „trivialer“ Unteraufrufe des Aufrufbaums
Φbf (n) = O(ξn) ,
wobei 0 < ξ ∈ IR eine (maximale, reelle, positive)Nullstelle des charakteristischen Polynomsbezeichne:
p(x) =∑`
α` · x−β` − 1
Fertilität kWievieleTeilaufgaben?
Diskont β`Argumentabzugfür den `-tenSelbstaufruf
Kopien α`Vielfachheit des`-tenSelbstaufrufs
Beweis.Wir wählen den Ansatz
Φb(n) = ξn
für eine beliebige reelle, positive Wurzel ξ des charakteristischen Polynoms p(·)und setzen ihn in die rechte Seite der Aufwandsrekursion ein:
k∑`=1
α`Φbf (n − β`) =
k∑`=1
α`ξ(n−β`) = ξn ·
k∑`=1
α`ξ−β` = ξn · 1 = Φb
f (n)
Der Ansatz erfüllt also das Rekursionsgesetz. Auch jedes Vielfache und jedeSumme gültiger Ansätze erfüllen die Rekursionsgleichung, also auch dieLinearkombination
Φbc1,...,ck (n) =
k∑i=1
ci · ξni , ξi Nullstelle von p(x).
Durch passende Wahl der Koeffizienten ci kann nun dafür gesorgt werden, daß
Φbc1,...,ck (n) = 1 (∀0 < n < maxβ`)
gilt. Der Kombinationsansatz ist offenbar von der Ordnung O(ξn) für die größteNullstelle ξ von p(x).
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Beispiele — Trivialfallaufrufe arithmetischer Reduktionen
FakultätsfunktionDas Polynom p(x) = x−1 − 1 besitzt die Nullstelle ξ = 1
Φbfak(n) = O(1n) = O(1)
Die lineare Rekursion für die Fakultätsfunktion besitzt einen Aufrufbaumin Kettenform, also — unabhängig vom Parameter n — genau einenBlattknoten.
FibonaccizahlenDas Polynom p(x) = x−1 + x−2−1 besitzt die Nullstellen ξ = 1/2(1±
√5)
Φbfib(n) = O(ξn) = O(Fn)
Die kaskadierte Rekursion besitzt O(ξn) viele terminale Aufrufe, also einevon n in exponentieller Weise abhängige Anzahl. Wie wir aus Kapitel 3wissen, besitzt die Folge ξn = (1/2(1 +
√5))n die Größenordnung der
Fibonacci-Folge selbst!
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Rekursionsformen
Effizienz
Entwurfstechniken
Teile & Herrsche
Dynamische Programmierung
Backtracking (Trial & Error)
Sortieren
Zusammenfassung
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Wechselgeld und Gier
WechselgeldaufgabeWieviele Münzen aus dem Währungssystem
C def= {C1, . . . ,CK}
werden zur Bezahlung des Betrages n ∈ INmindestens benötigt?
Tüte Brötchenvom Meisterbäcker69 = 50+ 10+ 5+ 2+ 2︸ ︷︷ ︸
5 Münzen
Gieriger Algorithmus〈Algorithmus〉
1 TRIVIALFALL. Wenn n = 0 dann µ(n) = 02 REDUKTION. Berechne die nächste Zahlmünze:
c∗ def= max {c ∈ C | c ≤ n}
3 REKURSION. Berechne µ(n − c∗)4 REKOMBINATION.
Das Ergebnis ist µ(n) = 1+ µ(n − c∗)〈Algorithmus〉
Gierige Lö-sungversagt seitErfindung deslegendären 23-Cent-Stücks!
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Divide & Conquer I
Symmetrisch reduzierende RekursionEs wird die Aufgabe gemäß n = n0 + n1 zerlegt und über alle möglichenn0 < n minimiert.
µ(n) =
{1 n ∈ Cmin0<i≤n/2 (µ(i) + µ(n − i)) sonst
Beispiel 691 1 6 50 10 5 2 1 682 2 5 50 10 5 2 673 2 1 6 50 10 5 1 664 2 2 5 50 10 5 655 5 5 50 10 2 2 646 5 1 6 50 10 2 1 63... . . . . . .
...33 20 10 2 1 8 20 10 5 1 3634 20 10 2 2 7 20 10 5 35
RechenaufwandErmittlung von µ(n)initiiert (n − 1)Selbstaufrufe µ(i),1 ≤ i < n.
ZerlegungkombinatorischeExplosion vonMehrfachberechnungen
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Divide & Conquer II
Asymmetrisch reduzierende RekursionEs wird die Aufgabe gemäß n = n0 + n1 zerlegt und über alle möglichenn0 ∈ C minimiert.
µ(n) =
{1 n ∈ Cmin` (1 + µ(n − c`)) sonst
Beispiel 691 1 vi 50 10 5 2 1 682 2 v 50 10 5 2 675 5 v 50 10 2 2 6410 10 v 50 5 2 2 5920 20 vi 20 20 5 2 2 4950 50 v 10 5 2 2 19
RechenaufwandErmittlung von µ(n)initiiert in der Regel |C|Selbstaufrufe µ(i),i ∈ C.
ZerlegungkombinatorischeExplosion vonMehrfachberechnungen
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Wechselgeldaufgabe mit DPSystematische einmalige Ermittlung aller Zwischenergebnisse µ(1), . . . , µ(n)
int changeDP (int n, int[] coin) {
int[] cmin = new int [n+1]; // Gedächtniscmin[0] = 0; // Leermenge
for (int cents = 1; cents <= n; cents++) { // Iterationint coins = cents; // geht immer
for (int k = 0; k < coin.length; k++) { // Münzvorratif (coin[k] > cents) continue; // zu groß!
final int used =1 + cmin [cents - coin[k]]; // Rekursion
if (used < coins)coins = used; // Bingo!
}cmin[cents] = coins; // Merken ...
}return cmin[n]; // Fazit
}
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Dynam. Programmierung — keine Mehrfachberechnung
GedächtnisFür jedes Zwischenergebnis wird vorab ein Speicherelementangelegt.
Kontrolle = IterationAlle Teilaufgaben werden nacheinander bearbeitet.• Lösungen wird in den Speicher geschrieben• zulässige Abfolge bei Speichertraversierung !
RekursionsformelSie steuert die Lösung der Teilaufgaben.• alle benötigten Teillösungen liegen bereits im Speicher.• keine Selbstaufrufe !!
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Levenshteindistanz zwischen Zeichenketten
T
R
I
E
B
T I G E R
TRIEBSubstitution
Insertion
Deletion
TIGER
TRIGER
TRIER
T R I E B
T I G E R
DefinitionIst A ein endliches Alphabet undsind x , y zwei Zeichenfolgen ausA?, so bezeichnet derLevenshtein-Abstand dLD(x , y)die minimale Anzahl vonElementaroperationen, mit denen xin y überführt werden kann.
Beispielberechnung� T I G E R
� 0 1 2 3 4 5T 1 0 1 2 3 4R 2 1 1 2 3 3I 3 2 1 2 3 4E 4 3 2 2 2 3B 5 4 3 3 3 3
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Beispiel — Dynamische Programmierung
Levenshteinalgorithmus mit 2D-Speicherint levenshtein (String x, String y) {
final int nx = x.length();final int ny = y.length();int[][] d = new int [nx+1][ny+1];
for (int i = 0; i <= nx; i++) d[i][0] = i;for (int j = 0; j <= ny; j++) d[0][j] = j;
for (int i = 1; i <= nx; i++)for (int j = 1; j <= ny; j++) {
final int mismatch = (x.charAt(i-1) == y.charAt(j-1)) ? 0:1;
final int sub = d[i-1][j-1] + mismatch;final int del = d[i-1][j] + 1;final int ins = d[i][j-1] + 1;
d[i][j] = Math.min (sub, Math.min (del, ins));}
return d[nx][ny];}
RechenaufwandO(nx · ny )
SpeicheraufwandO(nx · ny )
SpeicherüberlagerungO(min{nx , ny})
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Rekursionsformen
Effizienz
Entwurfstechniken
Teile & Herrsche
Dynamische Programmierung
Backtracking (Trial & Error)
Sortieren
Zusammenfassung
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Rundweg des Springers
1 60 39 34 31 18 9 6438 35 32 61 10 63 30 1759 2 37 40 33 28 19 836 49 42 27 62 11 16 2943 58 3 50 41 24 7 2048 51 46 55 26 21 12 1557 44 53 4 23 14 25 652 47 56 45 54 5 22 138×8 Feld 8250733 Aufrufe
RösslsprungaufgabeFinde zulässige Zugfolge, beginnend am Startfeld, ausschöpfend undohne Wiederholungen.
N 3 4 5 6 7 8 9(0,0) * * 8.840 248.169 7.151.179 8.250.733 ??(1,1) * *1.501 781.420 1.243.052 60.698.865 ?? ...
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Beispiel — Backtrackingprivate final static int[] X = {+2,+1,-1,-2,-2,-1,+1,+2};private final static int[] Y = {+1,+2,+2,+1,-1,-2,-2,-1};private static int dim; // BRETTGRÖSSEprivate static int[][] brett; // ZUGFOLGEMATRIXprivate static int calls = 0; // Aufrufzähler
static boolean backtrack // TREIBERAUFRUF:(int kx, int ky, int l) { // backtrack (i,j,1)
calls += 1;brett[kx][ky] = l; // VERSUCH ...if (l == dim*dim) return true; // TRIVIALFALL: FERTIG!
for (int move = 0; move < X.length; move++) {final int KX = kx + X[move]; // NEUE VERTIKALPOSITIONfinal int KY = ky + Y[move]; // NEUE HORIZONTALPOSITIONif (0 <= KX && 0 <= KY // ? Nord+Westgrenze
&& KX < dim && KY < dim // ? Süd+Ostgrenze&& brett[KX][KY] == 0 // ? freies Feld&& backtrack (KX, KY, l+1) // ? Fortsetzung
) return true; // ERFOLG!}brett[kx][ky] = 0; // ... UND IRRTUM:return false; // Geordneter Rückzug
}
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Backtracking — keine überflüssigen Berechnungen
GedächtnisZwischenergebnisse und Suchraumposition• Teillösungen in dynamisch erzeugten Speicherstellen• Position im Aufrufbaum liegt im Laufzeitkeller
Kontrolle = RekursionAlle Teilaufgaben werden verschachtelt bearbeitet.• Lösungen wird in den Speicher geschrieben• Abfolge gesteuert durch Rekursionsgleichung
TeilaufgabeRekursionsgleichung auswerten unter Rückgriff auf Teillösungen• per Speicherabruf oder Selbstaufruf
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Rekursionsformen
Effizienz
Entwurfstechniken
Teile & Herrsche
Dynamische Programmierung
Backtracking (Trial & Error)
Sortieren
Zusammenfassung
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Gieriges Sortieren — durch AuswählenReduktion · Rekombination
Rekursiv mit Listen
public static IntNode selectSort (IntNode list) {if (list.next == null) return list; // TRIVIALFALLfinal IntNode XMIN = list.minElement (); // KLEINE HÄLFTElist = list.erase (XMIN); // GROSSE HÄLFTElist = selectSort (list); // REKURSIONXMIN.next = list; // REKOMBINATIONreturn XMIN;
}
Iterativ mit Listenrr s s r s
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Gieriges Sortieren — durch EinfügenReduktion · Rekombination
Rekursiv mit Listen
public static IntNode insertSort (IntNode list) {if (list.next == null) return list; // TRIVIALFALLfinal IntNode HEAD = list; // KLEINE HÄLFTEfinal IntNode TAIL = list.next; // GROSSE HÄLFTElist = insertSort (TAIL); // REKURSIONreturn list.insert (HEAD); // REKOMBINATION
}
Iterativ mit Listens r rr ss
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Gieriges Sortieren
ReduktionKleine Hälfte (Einzelelement)große Hälfte (der Rest)
SpeicheraufwandO(n) ZusatzspeicherO(1) für „in-place“-Variante
RechenaufwandO(n2) für
{rekursivesiteratives
}Sortieren durch
{AuswählenEinfügen
}• (n − 1) Aufrufe/Schritte bis zum Trivialfall
• O(n) für das Auswählen des kleinsten ElementsO(n) für das Einfügen eines beliebigen Elements
• O(1) für den Zugriff auf das nächste ElementO(1) für das Anhängen des nächstkleineren Elements
Iteratives Sortieren durch Auswählen mit Feldern
1 2 i−1 i i+1 m. . . . . . n. . . . . .
maxindex
bereits sortiert noch nicht sortiert
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Teile & Herrsche — durch MischenReduktion · Rekombination
Rekursiv mit Listen
public static IntNode mergeSort (IntNode list) {if (list.next == null) return list; // TRIVIALFALLfinal IntNode BELLY = list.center (); // REDUKTIONfinal IntNode TOP = mergeSort (BELLY.next); // UNTERAUFRUF 1BELLY.next = null;final IntNode BOT = mergeSort (list); // UNTERAUFRUF 2return IntNode.merge (BOT, TOP); // REKOMBINATION
}
rekursiver Abstieg
MischenHalbieren
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Teile & Herrsche — durch MischenMischmethode für die Rekombination
Mischen zweier geordneter Listennach dem Reißverschlußprinzip in linearer Rechenzeit:
public static IntNode merge (IntNode r, IntNode s) {IntNode reval;if (r.data < s.data) { reval = r; r = r.next; }
else { reval = s; s = s.next; }reval.next = (r == null) ? s
: (s == null) ? r: IntNode.merge (r,s) ;
return reval;}
Rechenaufwand für das Sortieren durch MischenFertilität α = 2, Skalierung β = 2, Overhead k = 1
• O(1) Zerlegen und O(n) Mischen
O(n1 log n) wegen α = βk
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Teile & Herrsche — durch QuicksortReduktion · Rekombination
Rekursiv mit Listen
rekursiver Abstieg
Triage VerkettenPivot
Rechenaufwand für den Quicksort-AlgorithmusFertilität α = 2∗, Skalierung β = 2∗, Overhead k = 1
• O(n) Pivot-Triage und O(1) Rückverketten
O(n1 log n) wegen α = βk
O(n2) Schlechtfallaufwand bei systematisch randständigen Angelpunkten
Rekursiv mit Feldern
1 2 i−1 i i+1 m. . . . . . n. . . . . .
bereits sortiert noch nicht sortiert bereits sortiert
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Teile & Herrsche — durch Quicksort
Quicksort-Algorithmus mit Listenpublic static IntNode quickSort (IntNode list) {
if (list.next == null) return list; // TRIVIALFALLIntNode lo = null, eq = null, hi = null; // TRIAGE VIA ...final int pivot = list.data; // ANGELPUNKTfor ( ; list != null; list = list.next) // O(n)
if (list.data < pivot) lo = new IntNode (list.data, lo);else if (list.data > pivot) hi = new IntNode (list.data, hi);
else eq = new IntNode (list.data, eq);if (lo != null) lo = quickSort (lo); // UNTERAUFRUF 1if (hi != null) hi = quickSort (hi); // UNTERAUFRUF 2if (hi != null) eq.back().next = hi; // VERKETTE =+>if (lo != null) { // VERKETTE <+=+>
lo.back().next = eq;return lo;
} elsereturn eq;
}
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Rekursionsformen
Effizienz
Entwurfstechniken
Teile & Herrsche
Dynamische Programmierung
Backtracking (Trial & Error)
Sortieren
Zusammenfassung
Rekursionsformen Effizienz Entwurfstechniken D&C DP BT Sortieren Σ
Zusammenfassung
1. Funktionsdeklarationen mit Selbstaufrufen heißen rekursiv.
2. Je nach Struktur des Aufrufbaums unterscheiden wir schlichte, lineare,kaskadierte, geschachtelte und verschränkte Rekursion.
3. Durch die Einbettungstechnik lassen sich viele Aufgabenstellungen ineinfachere Formen (speziell Iteration) transformieren.
4. Der Rechen- und Speicheraufwand eines Algorithmus wird asymptotischdurch Landaus Komplexitätsklassen beschrieben.
5. Die Terminierung eines Algorithmus wird mit dem Majorantenkriteriumnachgewiesen.
6. Gierige Rekursion ist schnell, aber verfehlt u.U. das Optimalergebnis.
7. Teile&Herrsche-Rekursion ist wegen kombinatorischer Explosion desAufrufbaums (O(2n)) oft nicht die effizienteste Lösung.
8. Dynamische Programmierung verhindert zeitraubendeMehrfachberechnung durch iteratives Speichern der Zwischenergebnisse.
9. Backtracking verhindert das Bearbeiten überflüssiger Teilaufgaben durchKopplung von Zwischenspeicherung und rekursivem Abstieg.