Motivation Kap. 3: Sortieren (4) „Warum soll ich hier bleiben?“ Wir lernen Heap-Sort Professor Dr. Petra Mutzel Lehrstuhl für Algorithm Engineering, LS11 Fakultät für Informatik, TU Dortmund 7. VO DAP2 SS 2008 Petra Mutzel „Was ist daran denn besonders?“ Heap ist eine effiziente und immer wieder verwendete Datenstruktur 29. April 2008 DAP2 SS08 1 Übersicht Petra Mutzel DAP2 SS08 2 Quicksort - Varianten • Randomisierter Quicksort Nachtrag Quick-Sort: • Randomisierter Quick-Sort • Speicherreduktion auf O(log n) • Quicksort mit log(n) Speicher Heap-Sort Petra Mutzel DAP2 SS08 3 Petra Mutzel DAP2 SS08 Randomisierter Quick-Sort Randomisierter Quick-Sort Ziel: Laufzeit unabhängig von der „Qualität“ der Eingabefolge (vorsortiert, etc…) Randomisierte Algorithmen: Es lassen sich keine Best-Case und Worst-Case Beispiele mehr konstruieren! Aber: Natürlich kann der Worst-Case noch eintreten! 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 SS08 4 Man berechnet eine Erwartete Laufzeit = Erwartungswert der Laufzeit ≈ durchschnittliche Laufzeit Average-Case E[T(n)] = O(n log n) 5 Petra Mutzel DAP2 SS08 6 1 Quick-Sort mit log(n) Speicher Quick-Sort mit log(n) Speicher Bisher: O(n) Speicher l ... p-1 p Idee: Lange Teile sofort bearbeiten bisher p+1................ r (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) } 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 SS08 7 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) } Petra Mutzel DAP2 SS08 8 Insertion-Sort: einfach O(n2) Selection-Sort: Θ(n2) Merge-Sort: O(n log n) , nicht in-situ (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) } } DAP2 SS08 (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) } Was bisher geschah… p+1................ r Petra Mutzel Zwischenschritt Quick-Sort: praxis schnell O(n2) jetzt: Heap-Sort: O(n log n) , in-situ Auf Basis von Selection-Sort! 9 Selection-Sort… Petra Mutzel DAP2 SS08 10 Heap (=Haufen) GUT In jedem Schritt wird ein Schlüssel an seine richtige Position gesetzt Heap: eine neue Datenstruktur! Speicherung… SCHLECHT …weiterhin als Array (in-situ!) Suchen des richtigen Schlüssels: Θ(n) Interpretation… IDEE Den unsortierten Teil „vorsortieren” Schnelles Finden des nächsten Schlüssels Petra Mutzel DAP2 SS08 …als binärer Baum, an dessen Wurzel immer das größte Element stehen soll 11 Petra Mutzel DAP2 SS08 12 2 Definition Heap Heap: Interpretation 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. 12345678 Beispiel: 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 SS08 F=<8,6,7,3,4,5,2,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 13 Heap: Interpretation 1 6 2 3 3 8 5 4 6 5 7 2 1 Petra Mutzel S 7 4 Binärer Baum 1 8 DAP2 SS08 14 Wurzel Ebene 1 1 S Interpretation als Binärer Baum 2 O 3 Ebene 2 R Knoten 2 O 3 Elter / Vater R Kind = Einträge im Baum 4 T 5 I 6 N 7 G Ebene 3 4 T Kanten 2 3 4 5 6 7 Tiefe/Höhe des Baums 1 Ebene 1 2 Ebene 2 1 2 4 Ebene 3 4 T 15 8 Ebene 4 2k-1 2k-1 Ebene k 7 N 7 G Tiefe/Höhe des Baums S O 5 1 3 I 6 N R 7 G 3 # Knoten PRO Ebene 3 # Knoten PRO Ebene # Knoten BIS Ebene 1 6 Binärer Baum: maximal 2 Kinder pro Knoten I N G # Knoten BIS Ebene 1 S O R T I Blätter = Knoten ohne Kinder verbinden Knoten Speicherung als Array 5 1 Ebene 1 Tiefe/Höhe 1eines 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 4 Elementen? 6 N T 5 I 15 8 Ebene 4 2k-1 2k-1 Ebene k 7 7 G n = 2h hmax = log2 n Höhe des Heaps: O(log n) 3 Heap-Eigenschaft Heap–Eigenschaft: Schlüssel der Elternknoten ist größer gleich denen seiner Kinder Idee von Heap-Sort 1 2 Elemente im unsortierten Array so verschieben, dass die Heap-Eigenschaft erfüllt ist (CreateHeap) S O 3 R Größtes Element im Heap finden ist einfach Wurzel = erstes Element im Array Array A[1…n] ∀ Indizes i: A[i] ≥ A[2i] und A[i] ≥ A[2i+1] 4 T 5 I 6 N 7 G Wurzel aus Heap entfernen Heap-Eigenschaften wiederherstellen (Sifting) nicht erfüllt! falls diese Indizes existieren 1 2 3 4 S O R T 5 6 7 I N G Petra Mutzel CreateHeap Die Heapbedingung ist an den Blättern erfüllt. 1 2 Algorithmus procedure CREATEHEAP () { for i := n/2 … 1 { SIFTDOWN (i, n) } } S O 3 R 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 4 T 1 5 I 2 3 6 4 S O R T Petra Mutzel N 5 7 6 G 7 I N G DAP2 SS08 CreateHeap procedure CREATEHEAP () { for i := n/2 … 1 { SIFTDOWN (i, n) } } 20 CreateHeap Beobachtung Betrachte Knoten über den Blättern repariere Teilheap Bearbeite Baum von unten nach oben Teilbäume sind immer Heaps DAP2 SS08 21 CreateHeap 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 } } N 7 2i 5 G 2i+1 6 7 I N G 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 } } 4 HeapSort HeapSort procedure HEAPSORT () { CREATEHEAP () for k := n … 2 { vertausche A[1] und A[k] SIFTDOWN (1, k-1) } } 1 2 4 S 3 O 5 I 1 2 3 procedure HEAPSORT () { CREATEHEAP () for k := n … 2 { vertausche A[1] und A[k] SIFTDOWN (1, k-1) } } G T 6 4 R N 5 7 6 k G T 1 4 7 G T S R O I N G T Petra Mutzel DAP2 SS08 2 O G S G O 5 I 1 2 3 G S 3 6 4 R N 5 7 6 k T 7 G S O G S R G O I N T 25 HeapSort Petra Mutzel DAP2 SS08 26 HeapSort procedure HEAPSORT () { CREATEHEAP () for k := n … 2 { vertausche A[1] und A[k] SIFTDOWN (1, k-1) } } 1 4 2 O G 5 I 1 2 3 procedure HEAPSORT () { CREATEHEAP () for k := n … 2 { vertausche A[1] und A[k] SIFTDOWN (1, k-1) } } N R S 3 6 4 R N k N S 5 7 6 T 1 4 7 N R S O N R G I N S T Petra Mutzel DAP2 SS08 2 O I G 5 k RI 1 2 3 O R I 3 6 4 N S 5 7 6 T 7 O R I O I N G R I S T 27 HeapSort Petra Mutzel DAP2 SS08 28 HeapSort procedure HEAPSORT () { CREATEHEAP () for k := n … 2 { vertausche A[1] und A[k] SIFTDOWN (1, k-1) } } 1 2 4 I 3 k O G 5 R 1 2 3 procedure HEAPSORT () { CREATEHEAP () for k := n … 2 { vertausche A[1] und A[k] SIFTDOWN (1, k-1) } } O G N 6 4 G N S 5 7 6 T 4 7 O G N I G N O G R S T Petra Mutzel DAP2 SS08 1 2 G I O 5 R 1 2 3 G N I 3 6 4 k G N S 5 7 6 T 7 G N I G I G N O R S T 29 Petra Mutzel DAP2 SS08 30 5 HeapSort Analyse SiftDown 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 procedure SIFTDOWN (i, m) { while Knoten i hat Kinder ≤ m { j := Kind ≤ m mit größerem 2 Wert if A[i] < A[j] then { vertausche A[i] und A[j] i := j } else return 4 O } } G I 3 6 4 N S 5 7 6 T 7 Petra Mutzel DAP2 SS08 31 Analyse CreateHeap procedure CREATEHEAP () { for i := n/2 … 1 { SIFTDOWN (i, n) } } Schleife: O(n) mal Pro Schleife: O(log n) O(n log n) Es gilt sogar: O(n) 4 (ohne Beweis) G I 3 5 R 2 3 6 4 N S 5 7 6 T 7 G I N O R S T Petra Mutzel DAP2 SS08 32 Analyse HeapSort 1 2 1 O( Baumtiefe ) = O( log n ) G I G I N O R S T 1 I 3 O 5 R 1 2 3 procedure HEAPSORT () { CREATEHEAP() for k := n … 2 { vertausche A[1] und A[k] SIFTDOWN (1, k-1) } } G 6 4 N S 5 7 6 CreateHeap: O(n log n) Schleife: O(n) mal Pro Schleife: O(log n) T 7 Insgesamt: O(n log n) G I N O R S T Petra Mutzel DAP2 SS08 33 1 2 4 G I 3 O 5 R 1 2 3 6 4 N S 5 7 6 T 7 G I N O R S T Petra Mutzel DAP2 SS08 34 Eigenschaften 1 2 in-situ? G I 3 N stabil? adaptiv? 4 O 5 R 1 2 3 6 4 S 5 7 6 T 7 G I N O R S T Petra Mutzel DAP2 SS08 35 6