Wiederholung - Average-Case Laufzeit Average-case Laufzeit: • Betrachten alle Permutationen dern Eingabezahlen. • Berechnen für jede Permutation Laufzeit des Algorithmus bei dieser Permutation. • Average-case Laufzeit ist dann der Durchschnitt über all diese Laufzeiten. • Average-case Laufzeit ist die erwartete Laufzeit einer zufällig und gleichverteilt gewählten Permutation aus der Menge aller Permutationen der n Eingabezahlen. SS 2008 Datenstrukturen und Algorithmen 4. Average-Case 1 Average-Case – Insertion-Sort Satz 4.8: Insertion-Sort besitzt average-case Laufzeit Θ(n2). Beweis: Wir zeigen, mit Wahrscheinlichkeit 1/2 hat man mindestens n2/16 Vergleiche (Annahme: n ist gerade). • Sei Ln/2 die Menge der n/2 kleinsten Zahlen • Sei Un/2 die Menge der n/2 größten Zahlen • Ai: Ereignis, dass in einer zufälligen Permutation der n Zahlen genau i Elemente aus Un/2 in der ersten Hälfte der Permutation platziert sind. • Bi: Ereignis, dass in einer zufälligen Permutation der n Zahlen genau i Elemente aus Ln/2 in der ersten Hälfte der Permutation platziert sind. SS 2008 Datenstrukturen und Algorithmen 4. Divide & Conquer - Merge-Sort 2 Average-Case – Insertion-Sort 5 2 4 7 1 3 2 6 Ereignis A3 Ln/2 1 2 2 3 Un/2 4 5 6 7 • Pr[Un/4≤ i ≤ n/2 Ai] = ∑n/4≤ i ≤ n/2 Pr[Ai] • Pr[Ai] = Pr[Bi] → Pr[Ai] = Pr[An/2-i] • ∑0≤ i ≤ n/2 Pr[Ai] = 1 • ∑n/4≤ i ≤ n/2 Pr[Ai] = 1-∑0≤ i < n/4 Pr[Ai] = Pr[An/4] + 1-∑n/4≤ i ≤ n/2 Pr[Ai] • 2 ∑n/4≤ i ≤ n/2 Pr[Ai] = 1 + Pr[An/4] > 1 → ∑n/4≤ i ≤ n/2 Pr[Ai] > ½ • Mit Wahrscheinlichkeit 1/2 befindet sich mindestens die Hälfte von Un/2 in der ersten Hälfte und mindestens die Hälfte von Ln/2 in der zweiten Hälfte einer zufälligen Permutation. SS 2008 Datenstrukturen und Algorithmen 4. Average-Case 3 Average-Case Laufzeit InsertionSort(Array A) 1. for j ← 2 to length(A) do 2. key ← A[j] 3. i ← j-1 4. while i>0 and A[i]>key do 5. A[i+1] ← A[i] 6. i ← i-1 7. A[i+1] ← key Mit Wahrscheinlichkeit ½ gibt es mindestens n/4 Elemente A[j] in Ln/2 mit j ≥ n/2 Sei j ≥ n/2 und A[j] in Ln/2 Dann wird die while-Schleife mindestens n/4 mal durchlaufen. n2/16 Vergleiche Im Durchschnitt produziert Insertion-Sort mehr als n2/32 Vergleiche SS 2008 Datenstrukturen und Algorithmen 4. Average-Case 4 5. Divide & Conquer – Quicksort Quicksort ist wie Merge-Sort ein auf dem Divide&Conquer-Prinzip beruhender Sortieralgorithmus. Von Quicksort existieren unterschiedliche Varianten, von denen einige in der Praxis besonders effizient sind. Die worst-case Laufzeit von Quicksort ist Θ(n 2 ). Die durchschnittliche Laufzeit ist jedoch Θ(nlog(n )). Eine randomisierte Version von Quicksort besitzt erwartete Laufzeit Θ(nlog(n )). SS 2008 Datenstrukturen und Algorithmen 5. Divide & Conquer – Quicksort 5 Quicksort - Idee Eingabe: Ein zu sortierendes Teilarray A[p K r ]. Teilungsschritt: Berechne einen Index q , p ≤ q ≤ r und vertausche die Reihenfolge der Elemente in A[p K r ], so dass die Element in A[p Kq − 1] nicht größer und die Elemente in A[q + 1K r ] nicht kleiner sind als A[q ]. Eroberungsschritt: Sortiere rekursiv die beiden Teilarrays A[p Kq − 1] und A[q + 1K r ]. Kombinationsschritt: Entfällt, da nach Eroberungsschritt das Array A[p K r ] bereits sortiert ist. SS 2008 Datenstrukturen und Algorithmen 5. Divide & Conquer - Quicksort 6 Quicksort - Pseudocode Quicksort ( A,p,r ) 1. if p < r 2. then q ← Partition( A,p,r ) 3. Quicksort ( A,p,q-1) 4. Quicksort ( A,q + 1,r ) Aufruf, um Array A zu sortieren: Quicksort ( A,1,length[A]) SS 2008 Datenstrukturen und Algorithmen 5. Divide & Conquer - Quicksort 7 Partition - Pseudocode Partition( A,p,r ) 1. 2. 3. 4. 5. 6. 7. 8. x ← A[r ] i ← p-1 for j ← p to r-1 do if A[ j ] ≤ x then i ← i + 1 A[i ] ↔ A[ j ] A[i + 1] ↔ A[r ] return i + 1 SS 2008 Datenstrukturen und Algorithmen 5. Divide & Conquer - Quicksort 8 Illustration von Partition (1) i p,j 2 8 7 1 p,i j 2 8 7 p,i 2 8 j 7 1 p,i 2 8 j 1 SS 2008 7 1 3 3 3 3 5 6 r 4 6 r 4 5 6 r 4 5 r 4 5 6 Partition( A,p,r ) 1. 2. 3. 4. 5. 6. 7. 8. x ← A[r ] i ← p-1 for j ← p to r-1 do if A[ j ] ≤ x then i ← i + 1 A[i ] ↔ A[ j ] A[i + 1] ↔ A[r ] return i + 1 Datenstrukturen und Algorithmen 5. Divide & Conquer - Quicksort 9 Illustration von Partition (2) p i 2 1 7 p j 8 3 5 i 2 1 p 2 i 1 3 p 2 i 1 3 p 2 i 1 3 SS 2008 3 r 6 j 8 8 8 4 4 r 7 5 7 j r 5 6 4 7 5 r 6 4 5 r 6 8 7 6 4 Partition( A,p,r ) 1. 2. 3. 4. 5. 6. 7. 8. x ← A[r ] i ← p-1 for j ← p to r-1 do if A[ j ] ≤ x then i ← i + 1 A[i ] ↔ A[ j ] A[i + 1] ↔ A[r ] return i + 1 Datenstrukturen und Algorithmen 5. Divide & Conquer - Quicksort 10 Korrektheit von Partition - Invariante Invariante: Vor Durchlauf der Schleife in Zeilen 3-6 mit Index j gilt für jeden Index k: 1. Falls p ≤ k ≤ i , dann ist A[k ] ≤ x . 2. Falls i + 1 ≤ k ≤ j − 1, dann ist A[k ] > x . 3. Falls k = r , dann ist A[k ] = x . p i ≤x SS 2008 j >x r x Verhältnis unbekannt Datenstrukturen und Algorithmen 5. Divide & Conquer - Quicksort 11 Korrektheit von Partition (1) Initialisierung: Vor dem ersten Schleifendurchlauf gilt i = p − 1 und j = p . Daher gibt es in diesem Fall keine Indizes zwischen p und i (1.Bedingung) bzw. zwischen i + 1 und j − 1 (2.Bedingung). Die erste Zeile sorgt dafür, dass die 3.Bedingung ebenfalls erfüllt ist. Erhaltung: Unterscheiden zwei Fälle 1. 2. A[ j ] > x A[ j ] ≤ x . 1. Fall: Nur j wird erhöht. Damit wird dann 2.Bedingung auch für k=j erfüllt. SS 2008 Datenstrukturen und Algorithmen 5. Divide & Conquer - Quicksort 12 Erhaltung – 1.Fall p i ≤x p r x >x j i ≤x SS 2008 j >x r x >x Datenstrukturen und Algorithmen 5. Divide & Conquer - Quicksort 13 Korrektheit von Partition (2) 2. Fall A[ j ] ≤ x : Element A[ j ] kommt an Position i. Da A[ j ] ≤ x ist 1.Bedingung weiter erfüllt. Für neues A[ j − 1] gilt nach Voraussetzung A[ j − 1] > x . Damit ist 2. Bedingung erfüllt auch. SS 2008 Datenstrukturen und Algorithmen 5. Divide & Conquer - Quicksort 14 Erhaltung – 2.Fall p i j ≤x ≤x ≤x SS 2008 >x j i p r x r x >x Datenstrukturen und Algorithmen 5. Divide & Conquer - Quicksort 15 Korrektheit von Partition (3) Terminierung: Es gilt j=r und alle Elemente des Arrays wurden mit x verglichen. Zeile 9 stellt nun sicher, dass x zwischen die Elemente echt kleiner als x und die Element echt größer als x plaziert wird. Damit genügt die von Partition berechnet Aufteilung immer den Anforderungen von Quicksort. SS 2008 Datenstrukturen und Algorithmen 5. Divide & Conquer - Quicksort 16 Laufzeit von Partition Partition( A,p,r ) 1. 2. 3. 4. 5. 6. 7. 8. x ← A[r ] i ← p-1 for j ← p to r-1 do if A[ j ] ≤ x then i ← i + 1 A[i ] ↔ A[ j ] A[i + 1] ↔ A[r ] return i + 1 Pro Zeile konstante Zeit. Schleife Zeilen 3-6 wird n=r-p-mal durchlaufen. Satz 5.1: Partition hat Laufzeit Θ(n) bei Eingabe eines Teilarrays mit n Elementen. SS 2008 Datenstrukturen und Algorithmen 5. Divide & Conquer - Quicksort 17 Quicksort – Analyse Satz 5.2: Es gibt ein c>0, so dass für alle n und alle Eingaben der Größe n Quicksort mindestens Laufzeit cnlog(n) besitzt. Satz 5.3: Quicksort besitzt worst-case Laufzeit Θ(n 2 ). Satz 5.4: Quicksort besitzt average-case Laufzeit O (nlog(n )). Average-case Laufzeit: Betrachten alle Permutationen der n Eingabezahlen. Berechnen für jede Permutation Laufzeit von Quicksort bei dieser Permutation. Average-case Laufzeit ist dann der Durchschnitt über all diese Laufzeiten. SS 2008 Datenstrukturen und Algorithmen 5. Divide & Conquer - Quicksort 18 Quicksort – Analyse SS 2008 Datenstrukturen und Algorithmen 5. Divide & Conquer - Quicksort 19 Quicksort – Analyse SS 2008 Datenstrukturen und Algorithmen 5. Divide & Conquer - Quicksort 20 Quicksort – Analyse SS 2008 Datenstrukturen und Algorithmen 5. Divide & Conquer - Quicksort 21 Quicksort – Analyse SS 2008 Datenstrukturen und Algorithmen 5. Divide & Conquer - Quicksort 22 Quicksort – Analyse SS 2008 Datenstrukturen und Algorithmen 5. Divide & Conquer - Quicksort 23 Randomisiertes Quicksort (1) Schlechte Eingaben für Quicksort können vermieden werden durch Randomisierung, d.h. der Algorithmus wirft gelegentlich eine Münze, um sein weiteres Vorgehen zu bestimmen. Worst-case Laufzeit bei ungünstigen Münzwürfen immer noch Θ(n 2 ). Es gibt keine schlechten Eingaben. Dies sind Eingaben, bei denen Quicksort bei allen Münzwürfen Laufzeit Θ(n 2 ) besitzt. Laufzeit ist in diesem Modell erwartete Laufzeit, wobei Erwartungswert über Münzwürfe genommen wird. Erwartete Laufzeit ist Θ(nlog(n )). SS 2008 Datenstrukturen und Algorithmen 5. Divide & Conquer - Quicksort 24 Randomisiertes Quicksort (2) Randomized - Partition( A,p,r ) 1. i ← Random( p,r ) 2. A[r ] ↔ A[i ] 3. return Partition( A,p,r ) Hierbei ist Random eine Funktion, die zufällig einen Wert aus [pKr ] wählt. Dabei gilt für alle i ∈ [p K r ] : 1 Pr (Random( p,r ) = i ) = . r − p +1 SS 2008 Datenstrukturen und Algorithmen 5. Divide & Conquer - Quicksort 25 Randomisiertes Quicksort (3) Randomized - Quicksort ( A,p,r ) 1. if p < r 2. then q ← Randomized - Partition( A,p,r ) 3. Randomized - Quicksort ( A,p,q-1) 4. Randomized - Quicksort ( A,q + 1,r ) Satz 5.10: Die erwartete Laufzeit von RandomizedQuicksort ist Θ(nlog(n )). Dabei ist der Erwartungswert über die Zufallsexperimente in Randomized - Partition genommen. SS 2008 Datenstrukturen und Algorithmen 5. Divide & Conquer - Quicksort 26 Median-Quicksort (1) Verbesserung der Güte von Aufteilungen, indem nicht ein festes Element zur Aufteilung benutzt wird, sondern z.B. das mittlere von drei Elementen Zur Aufteilung benutzt wird. Können etwa drei zufällige Elemente wählen oder A[p], A[q ], A[r ] mit q : = ( p + r ) / 2 . Beide Varianten in der Praxis erfolgreich. Aber nur zufällige Variante kann gut analysiert werden: Θ(nlog(n )) erwartete Laufzeit. SS 2008 Datenstrukturen und Algorithmen 5. Divide & Conquer - Quicksort 27 Median-Quicksort (2) Median ( A, i, j, k ) 1. if ( A[i ] ≤ A[ j ]) ∧ ( A[k ] ≤ A[i ]) 2. then return i 3. else if ( A[i ] ≤ A[ j ]) ∧ ( A[k ] ≥ A[ j ]) 4. then return j 5. else return k Median - Partition( A,p,r ) 1. i ← Median( p,( p + r )/ 2,r ) 2. A[r ] ↔ A[i ] 3. return Partition( A,p,r ) SS 2008 Datenstrukturen und Algorithmen 5. Divide & Conquer - Quicksort 28 Median-Quicksort (3) Median - Quicksort ( A,p,r ) 1. if p < r 2. then q ← Median - Partition( A,p,r ) 3. Median - Quicksort ( A,p,q-1) 4. Median - Quicksort ( A,q + 1,r ) SS 2008 Datenstrukturen und Algorithmen 5. Divide & Conquer - Quicksort 29 6. Rekursionen Laufzeiten insbesondere von Divide&Conquer Algorithmen werden häufig durch Rekursionsgleichungen beschrieben. Werden eine Methode kennenlernen, um solche Gleichungen zu lösen, die Rekursionsbaum-Methode. Diese Methode kann verfeinert werden, um das Master Theorem für Rekursionsgleichungen zu beweisen. Formulieren das Master Theorem nur. Anwendung des Master Theorems mit großer Vorsicht! SS 2006 Datenstrukturen und Algorithmen 6. Rekursionsgleichungen 30 Rekursionsbaum für T(n)=aT(n/b)+f(n) f (n ) a f (n / b ) f (n / b ) a logb (n ) a f (n / b 2 ) f (n / b 2 ) L f (n / b 2 ) a L a L f (n / b ) L a L a f (n / b 2 ) f (n / b 2 )L f (n / b 2 ) a L a L a L f (n / b 2 ) f (n / b 2 )L f (n / b 2 ) a L a L a L M M M M M M M M M M M M M M Θ(1) Θ(1) Θ(1) Θ(1) Θ(1) Θ(1) Θ(1) Θ(1) Θ(1) Θ(1) Θ(1) Θ(1) Θ(1) Θ(1) n log b (a ) SS 2006 Datenstrukturen und Algorithmen 6. Rekursionsgleichungen 31 Rekursionsbaum und Summation f (n ) f (n ) a f (n / b ) f (n / b ) a logb (n ) a f (n / b 2 ) f (n / b 2 ) L f (n / b 2 ) a L a L a L a f (n / b 2 ) f (n / b 2 )L f (n / b 2 ) a L a L a ⋅ f (n / b ) f (n / b ) L a L a 2 ⋅ f (n / b 2 ) f (n / b 2 ) f (n / b 2 )L f (n / b 2 ) a L a L a L M M M M M M M M M M M M M M Θ(1) Θ(1) Θ(1) Θ(1) Θ(1) Θ(1) Θ(1) Θ(1) Θ(1) Θ(1) Θ(1) Θ(1) Θ(1) Θ(1) Θ(n logb (a ) ) n logb (a ) Insgesamt : Θ(n logb (a ) ) + logb ( n )−1 j j ( ) a f n / b ∑ j =0 SS 2006 Datenstrukturen und Algorithmen 6. Rekursionsgleichungen 32 Lösen durch Rekursionsbäume - Beispiel 3T (n / 4) + cn 2 , n > 1 Betrachten T (n ) = , c > 0. n =1 c , Erhalten durch Ignorieren der Abrundung und mit Rekursionsbaum 3 3 2 2 T (n ) = cn + cn + L + 16 16 log 4 ( n )−1 = ∑ i =0 log 4 ( n )−1 2 cn + cn log 4 ( 3 ) i 3 cn 2 + cn log4 (3 ) 16 . (3/16 )log (n ) − 1 2 = cn + cn log (3 ) = O (n 2 ) (3/16 ) − 1 4 4 SS 2006 Datenstrukturen und Algorithmen 6. Rekursionsgleichungen 33 Das Master-Theorem Satz 6.1 (Master Theorem für Rekursionsgleichungen): Seien a,b ≥ 1 Konstanten , sei f (n ) eine Funktion und sei T (n ) definiert durch die Rekursionsgleichung T (n ) = aT (n/b ) + f (n ). Hierbei kann n/b auch durch n/b oder n/b ersetzt werden. Dann kann T (n ) folgenderm aßen abgeschätzt werden. 1. Ist f (n ) = O (n logb (a )−ε ) für ε > 0, dann gilt T (n ) = O (n logb (a ) ). 2. Ist f (n ) = Θ(n logb (a ) ) , dann gilt T (n ) = O (n logb (a ) ⋅ log(n )). 3. Ist f (n ) = Ω(n logb (a )+ε ) für ε > 0, und ist af (n/b ) ≤ cf (n ) für eine Konstante c < 1 und n → ∞, dann gilt T (n ) = Θ(f (n )). SS 2006 Datenstrukturen und Algorithmen 6. Rekursionsgleichungen 34