Kap. 3: Sortieren (3) Professor Dr. Petra Mutzel Lehrstuhl für Algorithm Engineering, LS11 Fakultät für Informatik, TU Dortmund 6. VO DAP2 SS 2009 Petra Mutzel 30. April 2009 DAP2 SS09 1 Überblick • Quick-Sort • Analyse von Quick-Sort • Quick-Sort Varianten • Heap-Sort Petra Mutzel DAP2 SS09 2 Termine für Übungstests • 1. Übungstest: • Di 19. Mai, in der Vorlesung im AudiMax, Beginn: ab 12:15 Uhr, ab 12 Uhr anwesend sein wegen Sitzordnung • 2. Übungstest: • Di 16. Juni, in der VO im AudiMax, Beginn: ab 12:15 Uhr, ab 12 Uhr anwesend sein wegen Sitzordnung Petra Mutzel DAP2 SS09 3 Motivation „Warum soll ich hier bleiben?“ Wir lernen Quick-Sort „Was ist daran denn besonders?“ Quick-Sort gehört zu den „Top 10“ wichtigsten Algorithmen Petra Mutzel DAP2 SS09 4 Analyse von QuickSort: Average • Grundannahmen – alle Schlüssel sind verschieden – o.B.d.A. A[i]∈{1,2,…n} – alle Permutationen sind gleich wahrscheinlich • Jede Zahl k∈{1,2,…,n} tritt mit gleicher Wahrscheinlichkeit 1/n an Position n auf • Pivotelement k erzeugt zwei Folgen der Längen k-1 und n-k • Diese Folgen sind wieder zufällig: gilt Petra Mutzel DAP2 SS09 5 Analyse von QuickSort: Average • Teilt man sämtliche Folgen mit n Elementen mit dem Pivotelement (an der letzten Stelle), so erhält man sämtliche Folgen der Länge k-1 und n-k. Rekursionsgleichung der Laufzeitfunktionen: wobei die Summe über alle n möglichen Aufteilungen läuft und bn der Aufteilungsaufwand für eine Folge der Länge n ist. Petra Mutzel DAP2 SS09 6 Analyse von QuickSort: Average Einsetzen von T(0)=0: Lösung der Rekursionsgleichung: T(n)=Θ(n log n) Petra Mutzel DAP2 SS09 7 Beweis von Average-Case • Wir zeigen: T(n)=O(n log n) • T(n)=Ω(n log n) ähnlich (o.Bw.) Wir zeigen durch vollständige Induktion: es existieren c,n0>0, so dass für alle n≥n0: T(n) ≤ cn log n Wir wählen: n0=2. Induktionsanfang: n=2: T(2)=T(1)+bn=a+2b somit ist T(2)≤c2 log 2 g.d.w. c≥(a+2b)/2=a/2+b Petra Mutzel DAP2 SS09 8 Beweis von Average-Case ff Induktionsschluss: Sei nun n≥3, Beh. gilt für alle kleineren Werte: Diese Ungleichung gilt, falls c≥4b Wähle insgesamt c=max {a/2+b,4b} Eigenschaften von QuickSort • Anzahl der Schlüsselvergleiche: Cbest(n)=Cavg(n)=Θ(n log n); Cworst(n)=Θ(n2) • Eigenschaften: – in situ? Θ(n) zusätzlichen Speicher – adaptiv? – stabil? • sehr gut in der Praxis • es existieren viele Varianten Quicksort - Varianten • Randomisierter Quicksort • Quicksort mit log(n) Speicher Petra Mutzel DAP2 SS09 11 Randomisierter Quick-Sort Ziel: Laufzeit unabhängig von der „Qualität“ der Eingabefolge (vorsortiert, etc…) Idee: Wähle Pivotelement zufällig aus! Einfachste Umsetzung: „Neues“ Partitionieren: (1) z := Zufallszahl zwischen l und r (2) vertausche A[z] mit A[r] (3) normales Partitionieren Petra Mutzel DAP2 SS09 12 Randomisierter Quick-Sort Randomisierte Algorithmen: Es lassen sich keine Best-Case und Worst-Case Beispiele mehr konstruieren! Aber: Natürlich kann der Worst-Case noch eintreten! Man berechnet eine Erwartete Laufzeit = Erwartungswert der Laufzeit ≈ durchschnittliche Laufzeit Average-Case E[ T(n) ] = O(n log n) Petra Mutzel DAP2 SS09 13 Quick-Sort mit log(n) Speicher Bisher: O(n) Speicher l ... p-1 p p+1................ r Idee: Lange Teile sofort bearbeiten D.h.: Rekursiver Aufruf nur für kleinere Teile. diese Teile sind ≤ Hälfte der betrachteten Länge Tiefe der rekursiven Aufrufe: O(log n) Petra Mutzel DAP2 SS09 14 Quick-Sort mit log(n) Speicher Idee: Lange Teile sofort bearbeiten bisher Zwischenschritt (1) procedure QS(ref A,l,r) (2) if l < r then { (3) p := Partition(A,l,r) (4) QuickSort(A,l,p-1) (5) QuickSort(A,p+1,r) (6) } (1) procedure QS(ref A,l,r) (2) while l < r do { (3) p := Partition(A,l,r) (4) QuickSort(A,l,p-1) (5) l := p+1 (6) } Petra Mutzel DAP2 SS09 15 Quick-Sort mit log(n) Speicher l ... p-1 p Zwischenschritt (1) procedure QS(ref A,l,r) (2) while l < r do { (3) p := Partition(A,l,r) (4) QuickSort(A,l,p-1) (5) l := p+1 (6) } p+1................ r (1) procedure QS(ref A,l,r) (2) while l < r do { (3) p := Partition(A,l,r) (4) if p-l < r-p then { (5) QuickSort(A,l,p-1) (6) l := p+1 (7) } else { (8) QuickSort(A,p+1,r) (9) r := p-1 (10) } } Petra Mutzel DAP2 SS09 16 Was bisher geschah… Insertion-Sort: O(n2) einfach Selection-Sort: Θ(n2) Merge-Sort: O(n log n) nicht in-situ Quick-Sort: praxis schnell O(n2) Jetzt: Heap-Sort: O(n log n) , in-situ Auf Basis von Selection-Sort! Petra Mutzel DAP2 SS09 17 Übersicht Heap-Sort Einführung in Datenstruktur Heap Analyse von Heap-Sort Petra Mutzel DAP2 SS09 18 Selection-Sort… GUT In jedem Schritt wird ein Schlüssel an seine richtige Position gesetzt SCHLECHT Suchen des richtigen Schlüssels: Θ(n) IDEE Den unsortierten Teil „vorsortieren” Schnelles Finden des nächsten Schlüssels Petra Mutzel DAP2 SS09 19 Heap (=Haufen) Heap: eine neue Datenstruktur! Speicherung… …weiterhin als Array (in-situ!) Interpretation… …als binärer Baum, an dessen Wurzel immer das größte Element stehen soll Petra Mutzel DAP2 SS09 20 Definition Heap Eine Folge H=<k1,k2,…,kn> von Schlüsseln ist ein (Max-) Heap, wenn für jede Position i die folgende Heap-Eigenschaft erfüllt ist: Falls 2i≤n, so gilt ki≥k2i und falls 2i+1≤n so gilt ki≥k2i+1. Beispiel: 12345678 F=<8,6,7,3,4,5,2,1> Ähnlich sind Min-Heaps definiert. Dort gilt: Falls 2i≤n, so gilt ki≤k2i und falls 2i+1≤n so gilt ki≤k2i+1. Petra Mutzel DAP2 SS09 21 Heap: Interpretation F=<8,6,7,3,4,5,2,1> 1 Heap-Eigenschaft: Falls 2i≤n, so gilt ki≥k2i und falls 2i+1≤n so gilt ki≥k2i+1. Heap–Eigenschaft: Schlüssel der Elternknoten ist größer gleich denen seiner Kinder 2 8 6 3 7 4 3 8 5 4 6 5 7 2 1 Petra Mutzel DAP2 SS09 22 Heap: Interpretation 1 S Interpretation als Binärer Baum 2 4 T 1 Speicherung als Array O 3 5 I 2 3 6 4 S O R T R N 5 7 6 G 7 I N G Binärer Baum Wurzel Ebene 1 Ebene 2 Knoten 1 2 S O 3 Elter / Vater R Kind = Einträge im Baum Ebene 3 4 T Kanten verbinden Knoten 5 I 6 N 7 G Blätter = Knoten ohne Kinder Binärer Baum: maximal 2 Kinder pro Knoten Tiefe/Höhe des Baums 1 Ebene 1 2 Ebene 2 4 Ebene 3 4 T 15 8 Ebene 4 2k-1 2k-1 Ebene k 3 7 # Knoten PRO Ebene # Knoten BIS Ebene 1 1 2 S O 5 3 I 6 N R 7 G Tiefe/Höhe des Baums 3 # Knoten PRO Ebene # Knoten BIS Ebene 1 1 Ebene 1 Tiefe/Höhe eines 1 S Baums = Anzahl der Ebenen - 1 2 Ebene 2 Gegebene Höhe h: 3 R 2 O nmax = 2h+1-1 nmin = 2h 4 Maximale Höhe bei n Ebene 3 4Elementen? 6 N T 5 I 15 8 Ebene 4 2k-1 2k-1 Ebene k 7 G n = 2h hmax = log2 n 7 Höhe des Heaps: O(log n) Heap-Eigenschaft Heap–Eigenschaft: Schlüssel der Elternknoten ist größer gleich denen seiner Kinder 1 2 S O 3 R Array A[1…n] ∀ Indizes i: A[i] ≥ A[2i] und A[i] ≥ A[2i+1] falls diese Indizes existieren 4 T 5 I 6 N 7 G nicht erfüllt! 1 2 3 4 S O R T 5 6 7 I N G Idee von Heap-Sort Elemente im unsortierten Array so verschieben, dass die Heap-Eigenschaft erfüllt ist (CreateHeap) Größtes Element im Heap finden ist einfach Wurzel = erstes Element im Array Wurzel aus Heap entfernen Heap-Eigenschaften wiederherstellen (Sifting) Petra Mutzel DAP2 SS09 29 CreateHeap Beobachtung Die Heapbedingung ist an den Blättern erfüllt. 1 2 Algorithmus Betrachte Knoten über den Blättern repariere Teilheap Bearbeite Baum von unten nach oben Teilbäume sind immer Heaps 4 T 1 S O 3 5 I 2 3 6 4 S O R T Petra Mutzel R N 5 7 6 G 7 I N G DAP2 SS09 30 CreateHeap procedure CREATEHEAP () { for i := n/2 … 1 { SIFTDOWN (i, n) } } 1 S i 2 O procedure SIFTDOWN (i, m) { while Knoten i hat Kinder ≤ m { j := Kind ≤ m mit größerem Wert 5 I 6 4 T if A[i] < A[j] then { vertausche A[i] und A[j] 1 2 3 4 i := j S O R T } else return } } 3 R N 7 2i 5 G 2i+1 6 7 I N G CreateHeap procedure CREATEHEAP () { for i := n/2 … 1 { SIFTDOWN (i, n) } } 1 S i 2 O procedure SIFTDOWN (i, m) { 3 R while Knoten i hat Kinder ≤ m { j := Kind ≤ m mit größerem Wert 5 I 6 N 7 G 4 T if A[i] < A[j] then { 2i 2i+1 vertausche A[i] und A[j] 1 2 3 4 5 6 7 i := j S O R T I N G } else return } } CreateHeap Heap-Erstellung beendet i procedure CREATEHEAP () { for i := n/2 … 1 { SIFTDOWN (i, n) } } 1 S j 2 T procedure SIFTDOWN (i, m) { 3 R while Knoten i hat Kinder ≤ m { j := Kind ≤ m mit größerem Wert 5 I 6 N 7 G 4 O if A[i] < A[j] then { vertausche A[i] und A[j] 1 2 3 4 5 6 7 i := j S T R O I N G } else return } } HeapSort procedure HEAPSORT () { CREATEHEAP () for k := n … 2 { vertausche A[1] und A[k] SIFTDOWN (1, k-1) } } 1 2 4 G T S 3 O 5 I 1 2 3 6 4 R N 5 7 6 k G T 7 G T S R O I N G T Petra Mutzel DAP2 SS09 34 HeapSort procedure HEAPSORT () { CREATEHEAP () for k := n … 2 { vertausche A[1] und A[k] SIFTDOWN (1, k-1) } } 1 2 4 G S O G S 3 G O 5 I 1 2 3 6 4 R N 5 7 6 k T 7 G S O G S R G O I N T Petra Mutzel DAP2 SS09 35 HeapSort procedure HEAPSORT () { CREATEHEAP () for k := n … 2 { vertausche A[1] und A[k] SIFTDOWN (1, k-1) } } 1 2 4 N R S O 3 G 5 I 1 2 3 6 4 R N k N S 5 7 6 T 7 N R S O N R G I N S T Petra Mutzel DAP2 SS09 36 HeapSort procedure HEAPSORT () { CREATEHEAP () for k := n … 2 { vertausche A[1] und A[k] SIFTDOWN (1, k-1) } } 1 2 4 O RI O I 3 G 5 k RI 1 2 3 6 4 N S 5 7 6 T 7 O RI O I N G RI S T Petra Mutzel DAP2 SS09 37 HeapSort procedure HEAPSORT () { CREATEHEAP () for k := n … 2 { vertausche A[1] und A[k] SIFTDOWN (1, k-1) } } 1 2 4 O G N I 3 k O G 5 R 1 2 3 6 4 G N S 5 7 6 T 7 O G N I G N O G R S T Petra Mutzel DAP2 SS09 38 HeapSort procedure HEAPSORT () { CREATEHEAP () for k := n … 2 { vertausche A[1] und A[k] SIFTDOWN (1, k-1) } } 1 4 2 G I O 5 R 1 2 3 G NI 3 6 4 k G N S 5 7 6 T 7 G NI G I G N O R S T Petra Mutzel DAP2 SS09 39 HeapSort procedure HEAPSORT () { CREATEHEAP () for k := n … 2 { vertausche A[1] und A[k] SIFTDOWN (1, k-1) } } 1 4 2 k G I O 5 R 1 2 3 G I 3 6 4 N S 5 7 6 T 7 G I G I N O R S T Petra Mutzel DAP2 SS09 40