Kapitel 6 Elementare Sortieralgorithmen

Ähnliche Dokumente
8.1.3 Operation Build-Max-Heap Operation zur Konstruktion eines Heaps Eingabe: Feld A[1..n], n = länge(a) BUILD-MAX-HEAP (A)

Kap. 3: Sortieren. Überblick. Unser Sortierproblem. Motivation. Laufzeitmessung. Warum soll ich hier bleiben? Sortierverfahren sind WICHTIG!!!

Kapitel 8 Fortgeschrittene Sortieralgorithmen

8. Sortieren II. 8.1 Heapsort. Heapsort. [Max-]Heap 6. Heapsort, Quicksort, Mergesort. Binärer Baum mit folgenden Eigenschaften

Algorithmen und Datenstrukturen Heapsort

Übersicht. Datenstrukturen und Algorithmen. Übersicht. Divide-and-Conquer. Vorlesung 9: Quicksort (K7)

Abschnitt: Algorithmendesign und Laufzeitanalyse

Algorithmen und Datenstrukturen 1

Sortieralgorithmen. Jan Pöschko. 18. Januar Problemstellung Definition Warum Sortieren?... 2

Algorithmen und Datenstrukturen (Th. Ottmann und P. Widmayer) Folien: Einfache Sortierverfahren Autor: Stefan Edelkamp

Algorithmen und Datenstrukturen

JAVA - Suchen - Sortieren

7. Sortieren Lernziele. 7. Sortieren

Interne Sortierverfahren

Heapsort / 1 A[1] A[2] A[3] A[4] A[5] A[6] A[7] A[8]

Aufgabe 8. 1 Arbeitsweise illustrieren. 2 Korrektheitsbeweis führen. 3 Laufzeitanalyse durchführen.

Algorithmen und Datenstrukturen

Programmieren I. Kapitel 7. Sortieren und Suchen

Tutoraufgabe 1 (Sortieren): Lösung: Datenstrukturen und Algorithmen SS14 Lösung - Übung 4

Übung Algorithmen I

2.2 Allgemeine (vergleichsbasierte) Sortierverfahren

Alle bislang betrachteten Sortieralgorithmen hatten (worst-case) Laufzeit Ω(nlog(n)).

Übung Algorithmen I

Sortieralgorithmen. Selection Sort

Suchen und Sortieren

8. A & D - Heapsort. Werden sehen, wie wir durch geschicktes Organsieren von Daten effiziente Algorithmen entwerfen können.

3.2. Korrektheit und Komplexität am Beispiel: Sortieren Sortieren ist eine wichtige Basis-Operation für komplexe Algorithmen

4. Sortieren 4.1 Vorbemerkungen

Tutoraufgabe 1 (Sortieralgorithmus):

Grundlegende Sortieralgorithmen

Build-Max-Heap. Build-Max-HeappAq. Satz Nach Ablauf von Build-Max-Heap ist A ein Heap. Build-Max-Heap hat Laufzeit Opnq.

Pro Informatik 2009: Objektorientierte Programmierung Tag 17. Marco Block-Berlitz, Miao Wang Freie Universität Berlin, Institut für Informatik

Sortieren durch Mischen (Mergesort; John von Neumann 1945)

Prof. Dr. Margarita Esponda

Übung Algorithmen und Datenstrukturen

Algorithmik Übung 3 Prof. Dr. Heiner Klocke. Sortierfolge nach Werten: Bube Dame König As nach Farben: Karo ( ) Herz ( ) Piek ( ) Kreuz ( )

Kapitel 3 Zur Korrektheit und Effizienz von Algorithmen

2 Sortieren. Beispiel: Es seien n = 8 und a = i : a i : ϕ(i) : a ϕ(i) :

Algorithmen und Datenstrukturen

Erster Sortier-Algorithmus: Bubblesort

Algorithmen und Datenstrukturen SS09. Foliensatz 15. Michael Brinkmeier. Technische Universität Ilmenau Institut für Theoretische Informatik

Sortierverfahren. Sortierverfahren für eindimensionale Arrays

Algorithmen und Datenstrukturen 1

Algorithmen und Datenstrukturen. Kapitel 3: Sortierverfahren. Skript zur Vorlesung. Algorithmen und Datenstrukturen

Übung: Algorithmen und Datenstrukturen SS 2007

Datenstrukturen und Algorithmen

Algorithmen und Datenstrukturen

Übung Datenstrukturen. Sortieren

Algorithmen und Datenstrukturen 1-3. Seminar -

Algorithmen und Datenstrukturen

Algorithmen und Datenstrukturen

f 1 (n) = log(n) + n 2 n 5 f 2 (n) = n 3 + n 2 f 3 (n) = log(n 2 ) f 4 (n) = n n f 5 (n) = (log(n)) 2

2 Sortieren durch Vergleichen Eingabefolge a 1, a 2,..., a n 2, 1, 3 Sortieralg. Für festes n ist ein vergleichsbasierter Sortieralg. charakterisiert

2. Grundlagen. Beschreibung von Algorithmen durch Pseudocode. Korrektheit von Algorithmen durch Invarianten.

Untere Schranke für allgemeine Sortierverfahren

Bucketsort. Korrektheit. Beispiel. Eingabe: Array A mit n Elementen im Bereich [0,1) Annahme: die Elemente sind in [0,1) gleichverteilt.

Datenstrukturen und Algorithmen

Effizienz von Algorithmen

Algorithmen und Datenstrukturen (Th. Ottmann und P. Widmayer) Folien: Suchverfahren Autor: Stefan Edelkamp / Sven Schuierer

7. Übung zu Algorithmen I 1. Juni 2016

Asymptotische Laufzeitanalyse: Beispiel

Quicksort ist ein Divide-and-Conquer-Verfahren.

Beispiellösung zu den Übungen Datenstrukturen und Algorithmen SS 2008 Blatt 5

Algorithmen I. Tutorium 1-3. Sitzung. Dennis Felsing

Aufgabe (Schreibtischtest, Algorithmenanalyse)

Einführung in die Informatik 2

Algorithmen und Datenstrukturen (ESE) Entwurf, Analyse und Umsetzung von Algorithmen (IEMS) WS 2014 / Vorlesung 9, Donnerstag 18.

Suchen und Sortieren (Die klassischen Algorithmen)

Grundlagen der Programmierung 2. Sortierverfahren

Musterlösungen zu Datenstrukturen und Algorithmen SS 2005 Blatt 2, Aufgabe 3 Wir schreiben zunächst alle Funktionen zur Basis 2.

Informatik II Sortieralgorithmen

Algorithmen und Datenstrukturen

Kapitel 2. Sortieren. Adressenverwaltung (lexikographisch) Treerlisten bei Suchanfragen (Relevanz) Verdeckung (z-koordinate) ...

Vorlesung Informatik 2 Algorithmen und Datenstrukturen. (25 Sortieren vorsortierter Daten)

lim log 2n n = > 0 Da es einen Limes gibt, gibt es auch einen Limes inferior, der gleich diesem Limes ist.

5. Übungsblatt zu Algorithmen I im SoSe 2016

Übungsblatt 1. f(n) = f(n) = O(g(n)) g(n) = O(f(n)) Zeigen oder widerlegen Sie: 3 n = Θ(2 n ) Aufgabe 1.2 Gegeben sei die folgende Funktion:

Algorithmen und Datenstrukturen (Th. Ottmann und P. Widmayer) Folien: Spezielle Sortierverfahren Autor: Sven Schuierer

Die Schnittstelle Comparable

Suchen und Sortieren Sortieren. Heaps

2.3.1 Einleitung Einfache Sortierverfahren Höhere Sortierverfahren Komplexität von Sortierverfahren Spezielle Sortierverfahren

Definition Ein Heap (priority queue) ist eine abstrakte Datenstruktur mit folgenden Kennzeichen:

Übersicht. Berechnung der Potenz für zwei ganze Zahlen Klausuraufgabe SS 2010! Berechnung der Cosinus-Funktion Klausuraufgabe WS 2010/2011!

Algorithmen und Datenstrukturen

Grundlagen der Programmierung

Datenstrukturen und Algorithmen. 7. Suchen in linearen Feldern

Stand der Vorlesung Komplexität von Algorithmen (Kapitel 3)

4XLFNVRUW. Geschichte:

Transkript:

Kapitel 6 Elementare Sortieralgorithmen Ziel: Kennenlernen elementarer Sortierverfahren und deren Effizienz Zur Erinnerung: Das Sortier-Problem Gegeben: Folge A von n Elementen a 1, a 2,..., a n ; Eine lineare Ordnungsrelation auf A gegeben durch < Gesucht: Eine Permuation Π der n Elemente, so dass eine Folge a, a Π(1) Π(2),... a Π(n) entsteht mit a < a Π(1) Π(2),<...< a Π(n) (aufsteigende Folge) oder a > a Π(1) Π(2),>...> a Π(n) (absteigende Folge) AuD,Kapitel 6 Sortieralgorithmen, WS10/11, C. Eckert 1 Sortieren durch Vergleich Vergleich von je zwei Elementen (Vergleichsoperation) Anzahl der Schlüsselvergleiche ist untere Schranke für Laufzeit von Sortieralgorithmen: Laufzeit Sortieralgorithmus = O(Anzahl der Schlüsselvergleiche) Bekannte Sortierverfahren: (im Folgenden erklärt) Sortieren durch Tauschen: Selection Sort, O(n 2 ) Sortieren durch Einfügen, in-place Sortieren, O(n 2 ) Sortieren durch Mischen, nicht in-place, O(n log n) Quicksort, in-place, O(n 2 ) Heapsort, in-place, O(n log n) AuD,Kapitel 6 Sortieralgorithmen, WS10/11, C. Eckert 2 6.1 Selection Sort Sei eine Folge a 1,, a n von Schlüsseln gegeben, wobei ein Schlüssel a i an der i-ten Position in einem Feld A[1.. N] abgespeichert ist. Der Algorithmus Selection Sort ist wie folgt gegeben: For i=n downto 2 do m= Index des maximalen Schlüssels in A[1..i] vertausche A[i] und A[m] Grundlegende Idee: Satz Der Algorithmus Selection Sort benötigt zum Sortieren von n Elementen genau Vergleiche. Laufzeit ist: O(n 2 ) Beweis: AuD,Kapitel 6 Sortieralgorithmen, WS10/11, C. Eckert 3 AuD,Kapitel 6 Sortieralgorithmen, WS10/11, C. Eckert 4

6.2 Insertion Sort Sei eine Folge a 1,, a n von Schlüsseln gegeben. Der Algorithmus InsertionSort (vgl. Kapitel 3.2.1) arbeitet wie folgt: for j = 2 to n do key = A[ j ] // Füge A[ j ] in die sortierte Liste A[1.. j 1] ein. i = j 1 while i > 0 und A[ i ] > key do A[i + 1] = A[ i ] i = i 1 A[i + 1] = key Laufzeit: (Wiederholung) 6.3 Merge Sort Sei eine Folge a 1,, a n von Schlüsseln gegeben. Der Algorithmus Merge Sort ist wie folgt gegeben: MergeSort(A, p, r) if p < r then q = (p + r)/2 MergeSort(A, p, q) MergeSort(A, q + 1, r) Merge(A, p, q, r) mischen zweier sortierter Teilfolgen. Merge Sort sortiert ein Feld der Länge n mit maximal n log 2 n Vergleichen AuD,Kapitel 6 Sortieralgorithmen, WS10/11, C. Eckert 5 AuD,Kapitel 6 Sortieralgorithmen, WS10/11, C. Eckert 6 Merge Sort Divide-and-Conquer-Prinzip Teile: die zu sortierende Folge von Elementen in zwei Teilfolgen mit n/2 Elementen auf. Beherrsche: Sortiere die zwei Teilfolge rekursiv bis die Teilfolge nur noch 1 Element umfasst; die Teilfolge ist sortiert. Verbinde: mische die beiden sortierten Teilfolgen Beispiel MergeSort(A,p, r) if p < r then q = (p + r)/2 MergeSort(A, p, q) MergeSort(A, q + 1, r) Merge(A, p, q, r) Divide Aufwand: Zusätzlicher Speicher der Länge der zu sortierenden Folge notw. Aufteilen ist einfach/schnell, Conquer (Merge) ist aufwändig. 0 4 5 6 3 9 2 8 1 7 0 4 5 6 2 3 8 9 1 7 0 2 3 4 5 6 8 9 1 7 Conquer 0 1 2 3 4 5 6 7 8 9 AuD,Kapitel 6 Sortieralgorithmen, WS10/11, C. Eckert 7 AuD,Kapitel 6 Sortieralgorithmen, WS10/11, C. Eckert 8

Algorithmus Merge(A, p, q, r) Für die Indizes p, q, r des Feldes A gilt: p q < r. Die Teilfolgen A[p.. q] und A[q + 1.. r] sind bereits sortiert. Als Ergebnis ergibt sich eine sortierte Teilfolge A[p.. r]. Die Laufzeit von Merge ist O(n), wobei n = r p + 1. Beispiel Merge-Algorithmus Schritte 10-17 von Merge beim Aufruf Merge(A, 9, 12, 16). Vgl Cormen AuD,Kapitel 6 Sortieralgorithmen, WS10/11, C. Eckert 9 AuD,Kapitel 6 Sortieralgorithmen, WS10/11, C. Eckert 10 Beispiel Merge-Algorithmus (Forts.) Berechnen der Laufzeit von Merge-Sort: Zur Vereinfachung sei angenommen, dass n eine Potenz von 2 ist, also n = 2 k. Das Teilen führt dann zu Teilproblemen der Größe n/2. Berechnung der Laufzeit T(n): Teile, d.h. Ermittlung der Feld-Mitte, erfordert konstante Zeit, (i) Zeigt die Felder und Indizes nach der Terminierung; Teilfeld A[9.. 16] ist sortiert Beherrsche: 2 Teilprobleme der Größe n/2 werden rekursiv gelöst: Verbinde: das Mischen auf einem Teilfeld der Länge n erfordert AuD,Kapitel 6 Sortieralgorithmen, WS10/11, C. Eckert 11 AuD,Kapitel 6 Sortieralgorithmen, WS10/11, C. Eckert 12

Rekursive Aufteilung in Teilprobleme: D(n): Zeit zum Aufteilen, ist konstant (Finde Mitte): O(1) C(n): Zeit zum Mischen: O(n) Rekursionsgleichung: O(1) falls n=1 T(n) = 2T(n/2) + D(n) + C(n) = 2T(n/2) + O(n) falls n> 1 Rekursionsbaum der Baum besitzt log n +1 Ebenen Jede Ebene trägt die Zeit cn zu den Gesamtlaufzeit T(n) bei Wir formen die Gleichung um zu c falls n=1 T(n) = 2T(n/2) + cn falls n> 1 Zur Lösung der Gleichung: Rekusionsbaum (siehe nächste Folie): AuD,Kapitel 6 Sortieralgorithmen, WS10/11, C. Eckert 13 AuD,Kapitel 6 Sortieralgorithmen, WS10/11, C. Eckert 14 Die Zerlegung in Teilaufgaben terminiert, wenn nur noch einzelne Elemente vorhanden sind; Bei n=2 k zu sortierenden Elementen, muss man (log n = k)-mal aufteilen, d.h. wir erzeugen einen Rekursionsbaum mit log n Ebenen Jede Ebene trägt cn zu Gesamtkosten bei, also: cn log n + cn, also Aufwand zum Teilen: Ө(n log n) Zusammenfassung: Laufzeitverhalten von Merge: Das Mischen zweier sortierter Teilfolgen erfordert O(n) Schritte, mit n = r p + 1 Jede der Zeilen 1-3 und 8-11 erfordert konstante Zeit. Die for-schleifen (Zeilen 4-7) erfordern O(n 1 + n 2 ) = O(n). Teile: d.h. Ermittlung der Feld-Mitte, erfordert O(1). Beherrsche: rekursives Lösen der 2 Teilprobleme: 2T(n/2). Verbinde: das Mischen (s.o.) erfordert O(n). Insgesamt: T MergeSort (n) = O(n log n) AuD,Kapitel 6 Sortieralgorithmen, WS10/11, C. Eckert 15 AuD,Kapitel 6 Sortieralgorithmen, WS10/11, C. Eckert 16

Mergesort (rekursiv) mergesort(int a[],int b[],int l,int r) { /* rekursiver mergesort algorithmus */ if (l<r-1) { int m = (l+r)/2; mergesort(a,b,l,m); mergesort(a,b,m,r); merge(a,b,l,m,r); copy(b,a,l,r); merge(int a[],int b[],int l,int m,int r) { for (int i=l,int j=m,int k=l; k<r; k++){ if ((j r) ((i<m) && (a[i] a[j]))) b[k] = a[i++]; else b[k] = a[j++]; copy(int b[],int a[],int l,int r) { for (int i=l; i<r; i++) a[i] = b[i]; AuD,Kapitel 6 Sortieralgorithmen, WS10/11, C. Eckert 17 Mergesort (iterativ) mergesort(int a[],int b[],int n) { /* iterativer mergesort algorithmus */ for (int width=1; width<n; width*=2) { for (int i=0; i<n; i+=2*width) { int l = i; int m = min(n,i+width); int r = min(n,i+2*width); merge(a,b,l,m,r); copy(b,a,0,n); merge(int a[],int b[],int l,int m,int r) { for (int i=l, int j=m, int k=l; k<r; k++){ if ((j r) ((i<m) && (a[i] a[j]))) b[k] = a[i++]; else b[k] = a[j++]; copy(int b[],int a[],int l,int r) { for (int i=l; i<r; i++) a[i] = b[i]; AuD,Kapitel 6 Sortieralgorithmen, WS10/11, C. Eckert 18 Lessons Learned: Positives an Insertion Sort: In-Place sortierender Algorithmus, d.h. zu jedem Zeitpunkt wird nur eine konstante Anzahl von Elementen des Feldes außerhalb des Eingabefeldes gespeichert. Innere Schleifen sind kurz, für kleine Eingaben ist es ein schnelles Verfahren, aber im Worst-Case wird O(n 2 ) benötigt. Positives an Merge-Sort gutes Laufzeitverhalten für große Eingabegrößen n: O(n log n) geschickter Einsatz der Teile-und-Herrsche Technik. Gesucht: Ein Algorithmus, der in-place sortiert und O(n log n) benötigt! AuD,Kapitel 6 Sortieralgorithmen, WS10/11, C. Eckert 19 6.4 Quicksort (C.A.R Hoare 1962) Idee: Gegeben Feld A[p.. r] wähle ein Element q aus A[p.. r] als Vergleichs-Element (Pivot) aus. Mögliche Wahl des Pivots? In-Place-Sortierung mit Divide-and-Conquer-Verfahren: Teile: Zerlege A[p.. r] in zwei Teilfelder A[p.. q 1] und A[q + 1.. r] so, dass gilt: Für alle i in A[p.. q 1]: A[i] A[q] und für alle j in A[q + 1.. r]: A[q] A[j] < q q > q A[p.. r] AuD,Kapitel 6 Sortieralgorithmen, WS10/11, C. Eckert 20

Beherrsche: Sortieren der Teilfelder A[p.. q 1] und A[q + 1.. r] durch rekursiven Aufruf von Quicksort Verbinde: da in-place sortiert, kein Schritt notwendig, das Feld A[p.. r] ist sortiert. Damit ergibt sich der Algorithmus für Quicksort wie folgt: 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) Der Kern des Quicksort-Algorithmus ist der Algorithmus Partition, der das Feld A[p..r] in-place sortiert: PARTITION (A, p, r) 1. x A[r] 2. i p 1 3. for j p to r 1 4. do if A[j] x 5. then i i + 1 6 vertausche A[i] A[j] 7 vertausche A[i + 1] A[r] 8 return i + 1 4 Bereiche Java-Applet zur Veranschaulichung der Funktionsweise unter: http://www2.tcs.ifi.lmu.de/~gruberh/lehre/sorting/quick/quick.html AuD,Kapitel 6 Sortieralgorithmen, WS10/11, C. Eckert 21 AuD,Kapitel 6 Sortieralgorithmen, WS10/11, C. Eckert 22 Beispiel: Algorithmus Partition auf einem 8-elementigen Feld (a) Pivot-Element x = A[r] = 4 PARTITION (A, p, r) 1. x A[r] 2. i p 1 3. for j p to r 1 4. do if A[j] x 5. then i i + 1 6 vertausche A[i] A[j] 7 vertausche A[i + 1] A[r] 8 return i + 1 Beispiel: Algorithmus Partition auf einem 8-elementigen Feld (a) Pivot-Element x = A[r] = 4 Die beiden Teilfolgen 4 und 4 werden schrittweise erstellt. (b) Erster Schritt: die erste Teilfolge enthält zunächst nur Element A[p] = 2, die anderen Elemente sind noch nicht einsortiert. (c) (d) Die größere Teilfolge wächst um die Elemente 8 und 7. (i) Pivot-Element wird abschließend zwischen die sortierten Teilfolgen eingefügt. AuD,Kapitel 6 Sortieralgorithmen, WS10/11, C. Eckert 23 AuD,Kapitel 6 Sortieralgorithmen, WS10/11, C. Eckert 24

Eigenschaften des Algorithmus Partition Während der Ausführung des Algorithmus ist das Feld in vier (ggf. leere) Bereiche zerlegt. Für die for-schleife (Zeilen 3-6) definieren wir folgende Schleifeninvariante: Zu Beginn jeder Iteration der for-schleife gilt für jeden Feldindex k: 1. Für p k i gilt: A[k] x. 2. Für i + 1 k j 1 gilt: A[k] > x. 3. Für k = r gilt: A[k] = x. Zu zeigen: Die Invariante gilt vor der erste Iteration der for-schleife. Die Invariante bleibt auch nach jeder Iteration noch gültig. AuD,Kapitel 6 Sortieralgorithmen, WS10/11, C. Eckert 25 Korrektheitsbeweis in 3 Schritten: (1) Initialisierung: vor der ersten Schleifeniteration gilt: i = p 1, j = p Es gibt keinen Wert zwischen p und i und keine Werte zwischen i + 1 und j 1. Die ersten beiden Bedingungen der Schleifeninvariante sind erfüllt. Mit der Zuweisung in Zeile 1 gilt auch die dritte Bedingung. PARTITION (A, p, r) 1. x A[r] 2. i p 1 3. for j p to r 1 4. do if A[j] x 5. then i i + 1 6 vertausche A[i] A[j] 7 vertausche A[i + 1] A[r] 8 return i + 1 AuD,Kapitel 6 Sortieralgorithmen, WS10/11, C. Eckert 26 Korrektheitsbeweis in 3 Schritten: (1) Initialisierung: vor der ersten Schleifeniteration gilt: i = p 1, j = p Es gibt keinen Wert zwischen p und i und keine Werte zwischen i + 1 und j 1. Die ersten beiden Bedingungen der Schleifeninvariante sind erfüllt. Mit der Zuweisung in Zeile 1 gilt auch die dritte Bedingung. (2) Fortsetzung: Nach dem Test in Zeile 4 sind zwei Fälle zu betrachten: Fall (a): A[j] > x, nur j wird inkrementiert, die Schleifeninvariante gilt weiterhin. Fall (b): A[j] x, Austausch der Elemente A[i] und A[j], die Schleifeninvariante ist erfüllt. Die zwei Fälle in einer Iteration des Algorithmus Partition: (3) Terminierung: bei Terminierung gilt: j = r, jedes Feldelement gehört zu einer der drei durch die Invariante beschriebenen Mengen. AuD,Kapitel 6 Sortieralgorithmen, WS10/11, C. Eckert 27 AuD,Kapitel 6 Sortieralgorithmen, WS10/11, C. Eckert 28

6.5.2 Laufzeitverhalten von Quicksort Die Perfomanz von Quicksort hängt davon ab, wie gut die Zerlegung balanciert ist. im besten Fall ist Quicksort asymptotisch so schnell wie Sortieren durch Mischen, aber in-place und mit kleinen Konstanten-Werten im schlechtesten Fall kann Quicksort aber auch so langsam wie Sortieren mit Einfügen sein. (a) Best-Case Quicksort im Worst-Case: völlig unbalancierte Teilfelder Der schlechteste Fall ist, wenn die Zerlegung ein Teilfeld mit n 1 Elementen und eines mit 0 Elementen erzeugt (unbalanciert!). D.h. das Pivot-Element ist immer das größte oder immer das kleinste Element einer Teilfolge (k = n). (c) Average-Case (b) Worst-Case AuD,Kapitel 6 Sortieralgorithmen, WS10/11, C. Eckert 29 AuD,Kapitel 6 Sortieralgorithmen, WS10/11, C. Eckert 30 Eine solche unbalancierte Zerlegung tritt bei jedem rekursiven Aufruf auf. Damit ergibt sich für die Laufzeit von Quicksort: Zerlegen erfordert O(n) und T(0) = O(1) (rekursiver Aufruf auf Feld der Größe 0 terminiert sofort) Rekursionsgleichung: T(n) = T(n 1) + T(0) + O(n) = T(n 1) + O(n) d.h. Aufsummieren der rekursiven Aufrufe: Quicksort benötigt zum Sortieren eines Feldes der Länge n maximal O(n 2 ) Vergleiche. AuD,Kapitel 6 Sortieralgorithmen, WS10/11, C. Eckert 31 Quicksort besitzt im Worst-Case somit das gleiche Laufzeitverhalten wie Insertion-Sort. Zudem gilt: Quicksort benötigt eine Laufzeit von O(n 2 ) sogar dann, wenn das Feld bereits sortiert ist! Hier benötigt Insertion-Sort nur O(n). Quicksort im Best-Case: möglichst balancierte Zerlegung Der Algorithmus Partition erzeugt zwei Teilfelder der Größen n/2 bzw. n/2 1. man kann zeigen, dass in Best-Case gilt: T(n) = O(n log n). Quicksort im Average Case: es wird eine Mischung aus balancierten und unbalancierten Zerlegungen erzeugt. AuD,Kapitel 6 Sortieralgorithmen, WS10/11, C. Eckert 32

diese Mischung aus guten und schlechten Zerlegungen beeinflusst jedoch nicht das asymptotische Gesamtverhalten. Quicksort benötigt auch im mittleren Fall O(n log n). Fazit: Entscheidend für die Laufzeit des Quicksort-Algorithmus ist eine gute Wahl des Pivot-Elementes Pragmatische Regeln für die Wahl des Pivot-Elementes: Nimm das letzte Element der (Teil)-Folge als Pivot Nachteil: sehr schlechte Performanz bei vorsortierten Feldern Wähle das mittlere Element (Median) des ersten, mittleren und letzten Elements der Folge Wähle zufälliges Element (liefert Average Case). AuD,Kapitel 6 Sortieralgorithmen, WS10/11, C. Eckert 33 AuD,Kapitel 6 Sortieralgorithmen, WS10/11, C. Eckert 34 Quicksort in C quicksort(int A[],int l,int r) { if (l<r) { int pivot = partition(a,l,r,r); if (pivot-l<r-pivot) { quicksort(a,l,pivot-1); quicksort(a,pivot+1,r); else { quicksort(a,pivot+1,r); quicksort(a,l,pivot-1); int partition(int A[],int l, int r, int pivot) { int i=l-1; j=r; /*left and right pointer*/ swap(a[pivot],a[r]); /*move pivot to the right end */ pivot=r; while(i<j) { do i++; while((i<j)&&(a[i] < A[pivot])); do j--; while((j>i)&&(a[j] > A[pivot])); if (i j) swap(a[i],a[pivot]); else swap(a[i],a[j]); return i; AuD,Kapitel 6 Sortieralgorithmen, WS10/11, C. Eckert 35 Fazit: Bislang kennengelernt: Sortierverfahren, die auf Vergleichen von Werten basieren. Felder von n Elementen können in O(n log n) sortiert werden: dies ist für Merge-Sort und Heap-Sort im schlechtesten Fall eine obere Schranke. Quicksort erreicht sie im Mittel. Wir werden noch beweisen, dass Merge-Sort und Heap-Sort asymptotisch optimal sind. Es gibt kein anderes vergleichendes Sortierverfahren, das um mehr als einen Faktor c schneller ist. Aber: es gibt Nicht-vergleichende Sortierverfahren, deren Laufzeit linear ist: z.b. Radixsort, Bucketsort AuD,Kapitel 6 Sortieralgorithmen, WS10/11, C. Eckert 36