Info 2 Labor 1 Aufwandsabschätzung und Sortieralgorithmen Dipl.-Inf. Domenic Jenz 30. April 2010 Info 2 Labor 1 Outline Einleitung Aufwandsabschätzungen Landau-Symbole Beispielprobleme Einfache Sortieralgorithmen Bubble Sort Selection Sort Insertion Sort Interludium Info 2 Labor 1 Einleitung Einleitung Kursseite mit Materialien: http://informatikdhs.npage.de/ E-Mail: [email protected] Info 2 Labor 1 Aufwandsabschätzungen Landau-Symbole Landau-Symbole I Mit fleißigem Zählen kann man oft die Anzahl an Operationen als Funktion f (n) in Abhängigkeit von der Größe der Eingabedaten aufstellen. I Häufig interessiert aber nicht die genaue Anzahl an Operationen, sondern das asymptotische Laufzeitverhalten. I Dieses wird formal in den Landau-Symbolen erfasst. I Definition von ein paar der Interessantesten: f ∈ O(g) ⇔ ∃ c > 0 ∃ x0 > 0 ∀x > x0 : |f (x)| ≤ c · |g(x)| f ∈ Ω(g) ⇔ g ∈ O(f ) f ∈ Θ(g) ⇔ f ∈ O(g) ∧ g ∈ O(f ) Info 2 Labor 1 Aufwandsabschätzungen Landau-Symbole Häh ?!!! Die Definitionen etwas anders: I f ∈ O(g): f wächst nicht wesentlich schneller als g. Bei Polynomen: Grad von f ist höchstens so groß wie Grad von g. f (n) existiert. limn→∞ g(n) I f ∈ Ω(g): f wächst nicht wesentlich langsamer als g Bei Polynomen: Grad von f ist mindestens so groß wie Grad von g. I f ∈ Θ(g): f wächst genau so schnell wie g Bei Polynomen: der Grad von f ist gleich dem Grad von g. f (n) limn→∞ g(n) = c, c 6= 0 Info 2 Labor 1 Aufwandsabschätzungen Landau-Symbole Beispiele f(n) 7 log(n) + 42 2n n log(4n) + n 1 2 2 n + log n n3 − 4n2 2n 5n 7sin2 (n) √ n n O(n) + + + - O(n log n) + + + + - O(n2 ) + + + + + + O(en ) + + + + + + + + Ω(n2 ) + + + + - Θ(n2 ) + - Info 2 Labor 1 Aufwandsabschätzungen Landau-Symbole Was bedeutet also nun eine Verdoppelung der Problemgröße für die Laufzeit der Programme ? f (n) ∈ O(log(n)) : f(n) = 100 → f (2n) ≈ 101 → f (8n) ≈ 108 f (n) ∈ O(n) : f(n) = 100 → f (2n) ≈ 200 → f (8n) ≈ 800 f (n) ∈ O(n2 ) : f(n) = 100 → f (2n) ≈ 400 → f (8n) ≈ 6400 f (n) ∈ O(n3 ) : f(n) = 100 → f (2n) ≈ 800 → f (8n) ≈ 51200 f (n) ∈ O(2n ) : f(n) = 100 → f (2n) ≈ 10000 → f (8n) ≈ 1016 Bitte beachten: Die Größe der Probleme, die hier in 100 Zeiteinheiten berechnet werden kann ist natürlich unterschiedlich und wird mit jeder Zeile kleiner ! Info 2 Labor 1 Aufwandsabschätzungen Beispielprobleme Code 1 1 2 3 4 5 6 7 8 9 10 11 12 int getMax (int field[], int n) { int tempMax = field[0]; for (int i = 1; i < n; i++) { if (tempMax < field[i]) { tempMax = field[i]; } } return tempMax; } Laufzeitkomplexität ist in O(n) Info 2 Labor 1 Aufwandsabschätzungen Beispielprobleme Code 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 int getMaxProd (int field[], int n) { int tempMax = field[0]*field[1]; for (int i = 0; i < n; i++) { for (int j = i+1; j < n; j++) { if (tempMax < field[i]*field[j]) { tempMax = field[i] * field[j]; } } } return tempMax; } Laufzeitkomplexität ist in O(n2 ) Info 2 Labor 1 Aufwandsabschätzungen Beispielprobleme Code 3 1 2 3 4 5 6 7 8 9 10 11 12 13 14 void differentiate2 (int nodes[],int result[],int size) { int weights[3] = {1,-2,1}; result[0] = weights[1] * nodes[0] + weights[2] * nodes[1]; result[size-1] = weights[0] * nodes[size-2] + weights[1] * nodes[size-1]; for (int i = 1; i < size-1; i++){ result[i] = 0; for (int j = -1; j <= 1; j++){ result[i] += weights[j+1] * nodes[i+j]; } } } Laufzeitkomplexität ist in O(n) Info 2 Labor 1 Einfache Sortieralgorithmen Allgemeines I Die Aufgabe der Sortieralgorithmen ist es eine Liste mit Elementen anhand einer Ordnungsrelation zu sortieren. I Für die Implementierungen hier soll die Ordnungsrelation < auf den ganzen Zahlen verwendet werden (d.h. die Zahlen sollen aufsteigend sortiert werden). I Für die Aufwandsabschätzungen sollen die Vergleiche von Listenelementen abgeschätzt werden. Info 2 Labor 1 Einfache Sortieralgorithmen Ein ganz einfacher Sortieralgorithmus: Bogosort Gegeben sei eine Liste von Zahlen. 1. Überprüfe ob die Liste sortiert ist. 2. Wenn ja, dann höre auf und vermelde Erfolg 3. Wenn nein, mische die Liste zufällig durch und gehe zu Schritt 1 Aufwandsabschätzungen für diesen Algorithmus: I Best case: O(1) I Average case: O(n · n!) I Worst case: Algorithmus bricht nicht ab Da wird es wohl bessere Algorithmen geben... Info 2 Labor 1 Einfache Sortieralgorithmen Bubble Sort Bubble Sort I Es werden zwei benachbarte Elemente a[i] und a[i+1] verglichen. Falls a[i] > a[i+1] ist, werden die beiden vertauscht. I Danach wird das nächste Paar miteinander verglichen. I Ist man am Ende angelangt, beginnt man wieder am Anfang. I Das macht man solange bis es in einem Durchlauf keine Vertauschungen mehr gibt. Figure: Visualisierung von Bubblesort. Aus engl. Wikipedia Info 2 Labor 1 Einfache Sortieralgorithmen Bubble Sort Aufwandsabschätzung Bubblesort I Best Case: O(n) Die Liste ist schon sortiert: Vergleiche: n-1, Kopieraktionen: 0 Info 2 Labor 1 Einfache Sortieralgorithmen Bubble Sort Aufwandsabschätzung Bubblesort I I Best Case: O(n) Die Liste ist schon sortiert: Vergleiche: n-1, Kopieraktionen: 0 Average Case: O(n2 ) Vergleiche: ≈ 12 n2 , Kopieraktionen: ≈ 14 n2 Info 2 Labor 1 Einfache Sortieralgorithmen Bubble Sort Aufwandsabschätzung Bubblesort I I I Best Case: O(n) Die Liste ist schon sortiert: Vergleiche: n-1, Kopieraktionen: 0 Average Case: O(n2 ) Vergleiche: ≈ 12 n2 , Kopieraktionen: ≈ 14 n2 Worst Case: O(n2 ) Die Liste ist P verkehrtrum sortiert: n·(n−1) Vergleiche: n−1 ≈ 12 n2 , i=1 i = 2 Kopieraktionen: n·(n−1) ≈ 12 n2 2 Info 2 Labor 1 Einfache Sortieralgorithmen Selection Sort Selection Sort I Das Feld sei in einen sortierten und unsortierten Bereich aufgeteilt. Am Anfang gehört alles zum unsortierten Bereich. I Finde das Minimum aus dem unsortierten Bereich I Vertausche es mit dem ersten Element des unsortierten Bereichs Info 2 Labor 1 Einfache Sortieralgorithmen Selection Sort Aufwandsabschätzung Selection Sort I Best Case: O(n2 ) Die Liste ist P schon sortiert: n·(n−1) ≈ 12 n2 , Vergleiche: n−1 i=1 i = 2 Kopieraktionen: 0 Info 2 Labor 1 Einfache Sortieralgorithmen Selection Sort Aufwandsabschätzung Selection Sort I I Best Case: O(n2 ) Die Liste ist P schon sortiert: n·(n−1) ≈ 12 n2 , Vergleiche: n−1 i=1 i = 2 Kopieraktionen: 0 Average Case: O(n2 ) Vergleiche: n·(n−1) ≈ 21 n2 , Kopieraktionen: ≈ 3n 2 Info 2 Labor 1 Einfache Sortieralgorithmen Selection Sort Aufwandsabschätzung Selection Sort I I I Best Case: O(n2 ) Die Liste ist P schon sortiert: n·(n−1) ≈ 12 n2 , Vergleiche: n−1 i=1 i = 2 Kopieraktionen: 0 Average Case: O(n2 ) Vergleiche: n·(n−1) ≈ 21 n2 , Kopieraktionen: ≈ 3n 2 Worst Case: O(n2 ) Die Liste ist verkehrtrum sortiert: Vergleiche: n·(n−1) ≈ 21 n2 , 2 Kopieraktionen: 3(n − 1) ≈ 3n Info 2 Labor 1 Einfache Sortieralgorithmen Insertion Sort Insertion Sort I Das Feld sei in einen sortierten und unsortierten Teil aufgeteilt. I Am Anfang ist natürlich nur das erste Element im sortierten Teil und der ganze Rest bildet den unsortierten Teil I In jedem Schritt wird das erste Element aus dem unsortierten Teil genommen und an die richtige Stelle im sortierten Teil eingefügt. Info 2 Labor 1 Einfache Sortieralgorithmen Insertion Sort Aufwandsabschätzung Insertion Sort I Best Case: O(n) Die Liste ist schon sortiert: Vergleiche: n-1, Kopieraktionen: 0 Info 2 Labor 1 Einfache Sortieralgorithmen Insertion Sort Aufwandsabschätzung Insertion Sort I I Best Case: O(n) Die Liste ist schon sortiert: Vergleiche: n-1, Kopieraktionen: 0 Average Case: O(n2 ) Vergleiche: ≈ 14 n2 , Kopieraktionen: ≈ 14 n2 Info 2 Labor 1 Einfache Sortieralgorithmen Insertion Sort Aufwandsabschätzung Insertion Sort I I I Best Case: O(n) Die Liste ist schon sortiert: Vergleiche: n-1, Kopieraktionen: 0 Average Case: O(n2 ) Vergleiche: ≈ 14 n2 , Kopieraktionen: ≈ 14 n2 Worst Case: O(n2 ) Die Liste ist P verkehrtrum sortiert: n·(n−1) ≈ 12 n2 , Vergleiche: n−1 i=1 i = Pn−1 2 2 Kopieraktionen: i=1 i + n − 1 = n +n−2 ≈ 12 n2 2 Info 2 Labor 1 Einfache Sortieralgorithmen Interludium Gibt es nichts besseres als O(n2 ) ? I I I Die bisherigen, recht einfachen Algorithmen hatten alle nur durchschnittliche Laufzeiten in O(n2 ) Gerade bei großen Datensätzen ist das zu langsam. Überlegen wir uns doch mal für eine Liste der Länge n: I I I I Es gibt n · (n − 1) · (n − 2) · · · · · 1 = n! mögliche Permutationen der Liste, von denen eine die sortierte Liste ist. Die Tiefe des optimalen Entscheidungsbaums (Knoten sind Vergleiche, Blätter resultierende Permutationen) ist dann dlog(n!)e Mit kann zeigen, daß log(n!) ∈ O(nlog(n)) und sogar log(n!) ∈ Θ(nlog(n)) ist. Es kann also bessere Algorithmen geben als die bisherigen, die aber nicht schneller sein können als in O(nlog(n)), wenn verglichen wird. Info 2 Labor 1 Einfache Sortieralgorithmen Interludium Praxisteil I Laden Sie die Dateien main.cpp, sorting.h, sorting.cpp von der Kursseite http://informatikdhs.npage.de/ herunter I Füllen Sie die Funktionsrümpfe für die Funktionen bubbleSort, selectionSort und insertionSort aus. I Die Funktionen bekommen beim Aufruf in main.cpp dann die zu sortierende Liste und die Größe der Liste. I Zählen Sie dabei die Anzahl der Vergleiche zwischen Listenelementen in der Variablen counter ! I Nach dem Ende der Sortierfunktion soll die zuvor übergebene Liste sortiert sein. I Probieren Sie auch andere Listen aus, auch größere, zufällig generierte !