Algorithmen. Sortieren 6/1

Ähnliche Dokumente
Sortieralgorithmen. Selection Sort

UE Algorithmen und Datenstrukturen 1 UE Praktische Informatik 1. Übung 9. Sortieren

Tutoraufgabe 1 (Sortieralgorithmus):

(08 - Einfache Sortierverfahren)

Elementare Sortierverfahren

Prof. Dr. Margarita Esponda

Übung: Algorithmen und Datenstrukturen SS 2007

Suchen und Sortieren Sortieren. Heaps

Sortierverfahren. Sortierverfahren für eindimensionale Arrays

Interne Sortierverfahren

Datenstrukturen & Algorithmen

Algorithmen und Datenstrukturen I

Programmieren I. Kapitel 7. Sortieren und Suchen

Algorithmen und Datenstrukturen 1

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

Datenstrukturen und Algorithmen

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

Algorithmen und Datenstrukturen 12

Priority Queues and Heapsort

Grundlagen der Programmierung 2. Sortierverfahren

7. Übung zu Algorithmen I 1. Juni 2016

QuickSort ist ein Sortieralgorithmus, der auf der Idee des Teile & Beherrsche beruht, und das gegebene Array an Ort und Stelle (in place) sortiert

7. Sortieren Lernziele. 7. Sortieren

Sortieren und Suchen. Hallo Welt Seminar Jochen Gierling

Einführung in die Informatik Algorithmen und Datenstrukturen. Thema 17 Sortieren

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

Algorithms & Data Structures 2

Sortieren II / HeapSort Heaps

Algorithmen und Datenstrukturen

Programmieren in C. Strukturen und Zeiger. Prof. Dr. Nikolaus Wulff

A7.1 Untere Schranke. Algorithmen und Datenstrukturen. A7.1 Untere Schranke. Algorithmen und Datenstrukturen. A7.2 Quicksort. A7.

Algorithmen und Datenstrukturen 1-3. Seminar -

Abschnitt 19: Sortierverfahren

Algorithmen und Datenstrukturen 1

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

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

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

Sortierverfahren für Felder (Listen)

Suchen und Sortieren

Programmiertechnik II

Sortieralgorithmen. Direkte Sortierverfahren & Shellsort, Quicksort, Heapsort. Vorlesung Algorithmen und Datenstrukturen 2 im SS 2004

Grundlagen der Programmierung

Kapitel 10. Komplexität von Algorithmen und Sortieralgorithmen

Praktische Informatik I - Algorithmen und Datenstrukturen Wintersemester 2006/07

Suchen und Sortieren (Die klassischen Algorithmen)

JAVA - Suchen - Sortieren

Inhaltsverzeichnis. Teil 1 Grundlagen 23

Inhaltsverzeichnis. Teil 1 Grundlagen 21. Teil 2 Datenstrukturen 85

Datenstrukturen. Sortieralgorithmen. am Beispiel Java. c Y. Pfeifer. (Mai 2013)

Kapitel 6 Elementare Sortieralgorithmen

Was bisher geschah Funktionale Programmierung in Haskell: Algebraische Datentypen Pattern Matching Polymorphie Typklassen Rekursive Datentypen:

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)

Aufgabenblatt: Arrays

Übung Algorithmen und Datenstrukturen

Sortieren und Suchen. Jens Wächtler Hallo Welt! -Seminar LS 2

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

Kapitel 9. Komplexität von Algorithmen und Sortieralgorithmen

Informatik-Seminar Thema 6: Bäume

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

Übung Algorithmen und Datenstrukturen

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

Vorlesung Datenstrukturen

Vorlesung Datenstrukturen

Algorithmen und Datenstrukturen

Informatik II Prüfungsvorbereitungskurs

Sortieren Anordnen einer gegebenen Menge von Objekten in einer bestimmten Ordnung.

Sortieren durch Einfügen (Insertion Sort) fügt die restlichen Elemente nach und nach in die bereits sortierte Liste der abgearbeiteten Zahlen.

Teil 1: Suchen. Ausgeglichene Bäume B-Bäume Digitale Suchbäume. M.O.Franz, Oktober 2007 Algorithmen und Datenstrukturen - Binärbäume 1-1

Robert Sedgewick. Algorithmen in Java. Teil 1-4 Grundlagen Datenstrukturen Sortieren Suchen. Java-Beratung durch Michael Schidlowsky

Übungsklausur Algorithmen I

Kapitel 8 Fortgeschrittene Sortieralgorithmen

Robert Sedgewick. Algorithmen in Java. »il 1-4 Grundlagen Datenstrykturen Sortleren Suchen. java-beratung durch Michael Schidlowsky

Agenda. 1 Einleitung. 2 Binäre Bäume. 3 Binäre Suchbäume. 4 Rose Trees. 5 Zusammenfassung & Ausblick. Haskell Bäume. Einleitung.

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

Heapsort, Quicksort, Mergesort. 8. Sortieren II

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

Aufgabe (Schreibtischtest, Algorithmenanalyse)

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

Programmierung mit C Algorithmen

Kapitel 9. Komplexität von Algorithmen und Sortieralgorithmen

Sortieren durch Mischen (Mergesort; John von Neumann 1945)

Ü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:

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

Mathematik AG. Geschickt gesucht ist halb gefunden: Suchen und Sortieren mit Mathe

Informatik II Vorlesung am D-BAUG der ETH Zürich

Sortieralgorithmen. Inhalt: InsertionSort BubbleSort QuickSort. Marco Block

Transkript:

Algorithmen Sortieren 6/1

Problemstellung Gegeben ist ein Array von Daten Gesucht ist die Umordnung des Arrays anhand eines Sortierkriteriums Vereinfacht hier statt Schlüssel und Vergleichsfunktion einfache numerische Ordnung der Werte Üblicherweise Aufwand für Vergleiche und Umordnung der Elemente deutlich verschieden 6/2

Selection Sort Auswahl des kleinsten/größten Elements Vertauschen des ersten/letzten und des kleinsten/größten Elements Wiederholung mit dem Restfeld O(n) Vertauschungen O(n²) Vergleiche => beliebt für große Datensätze 6/3

Selection Sort selectionsort :: Ord a => [a] -> [a] selectionsort [] = [] selectionsort xs = m : selectionsort (r1 ++ r2) where m = foldl1 min xs (r1, (_:r2)) = break (== m) xs 6/4

Selection Sort Code void selectionsort(int* data, int len) { int i,m,k; for(i=0; i<len; i++) { /* von vorn nach hinten */ for(m=i, k=i+1; k<len; k++) if(data[k]<data[m]) /* neues Minimum gefunden? */ m = k; swap(data, i, m); /* Minimum nach vorn tauschen */ 6/5

Insertion Sort Einsortieren von Elementen in schon sortierte Teile Beginnend links/rechts die Elemente nach links/rechts einsortieren O(n²) Vergleiche O(n²) Vertauschungen O(n) bei fast sortierten Mengen => Ideal zum Nach- oder Fertigsortieren 6/6

Insertion Sort insertionsort :: Ord a => [a] -> [a] insertionsort = foldr insert [] insert :: Ord a => a -> [a] -> [a] insert x [] = [x] insert x (y:ys) x <= y = x : y : ys otherwise = y : insert x ys 6/7

Insertion Sort Code void insertionsort(int* data, int len) { int i,k; for(i=len; i-->0; ) { /* von hinten nach vorn */ for(k=i; k<len-1 && data[k] > data[k+1]; k++) swap(data, k, k+1); /* nach hinten schieben */ 6/8

Bubble Sort Durchlaufen der Menge und vertauschen zweier benachbarter Elemente, falls nötig Abbruch wenn keine Vertauschungen mehr ausgeführt wurden O(n²) Vertauschungen O(n²) Vergleiche Höchst ineffizientes Verfahren 6/9

Bubble Sort bubblesort :: Ord a => [a] -> [a] bubblesort [] = [] bubblesort xs = y : bubblesort ys where (y:ys) = bubble xs -- das kleinste Element ist gefunden bubble (x:xs@(_:_)) -- noch zwei Elemente da x <= y = x : y : ys otherwise = y : x : ys where (y:ys) = bubble xs bubble xs = xs 6/10

Bubble Sort Code void bubblesort(int* data, int len) { int i,k; for(i=0; i<len; i++) for(k=len-1; k-->i; ) /* Blasen von hinten nach vorn */ if(data[k] > data[k+1]) /* blubbern lassen */ swap(data, k, k+1); 6/11

Shell Sort Insertion Sort über größere Entfernungen Unterschiedliche Entfernungsraster anwenden Ergebnis ist eine fast sortierte Datei Abschließend Insertion Sort mit 1-er Raster Verfahren empfindlich für Rasterabfolge Laufzeit gut, aber theoretisch nicht untermauert => gutes Allzwecksortierverfahren 6/12

Shell Sort shellsort :: Ord a => [a] -> [a] shellsort xs = foldr hsort xs. (1:). takewhile ((length xs `div` 3) >=) $ iterate (\x -> 3*x+1) 4 hsort :: Ord a => Int -> [a] -> [a] hsort n = concat. transpose. map insertionsort. transpose. groupevery n 6/13

Shell Sort groupevery :: Int -> [a] -> [[a]] groupevery n xs = case splitat n xs of (y,[]) -> [y] (y,ys) -> y : groupevery n ys 6/14

Shell Sort Code void shellsort(int* data, int len) { int s,o,i,k; for(s=1; s<len; s=3*s+1) { /* maximale Schrittweite */ while((s/=3) > 0) for(o=0; o<s; o++) /* Alle Streifen */ for(i=len-o; (i-=s)>=0; ) /* insertionsort mit Schritt */ for(k=i; k<len-o-s && data[k] > data[k+s]; k+=s) swap(data, k, k+s); 6/15

Distribution Counting Beschränkte Wertemenge lassen sich zählen Zählung ergibt direkt den Zielplatz des Wertes Erfordert umkopieren, jedoch keine Vergleiche O(n) Zeitbedarf für alle Fälle O(n+m) Platzbedarf m ist der Wertebereich => Ideal zur Erstsortierung unsortierter Bestände 6/16

Distribution Counting Code distributioncounting :: Ix a => [a] -> [a] distributioncounting = concatmap (\(x,c) -> replicate c x). histogramm histogramm :: Ix a => [a] -> [(a,int)] histogramm xs = assocs $ sumup xs [(x,1) x <- xs] where sumup :: Ix a => [a] -> [(a,int)] -> UArray a Int sumup xs = accumarray (+) 0 (foldl1 min xs, foldl1 max xs) 6/17

Distribution Counting Code void distributioncounting(int* data, int len){ int i, min, max, *temp, *count; for(min=max=data[i=0]; i<len; i++) { min = min < data[i]? min : data[i]; max = max > data[i]? max : data[i]; for(i=0; i<len; i++) count[(temp[i] = data[i])-min]++; for(i=min; i<max; i++) count[i+1-min] += count[i-min]; for(i=len; i-->0;) data[--count[temp[i]-min]] = temp[i]; temp = malloc(len * sizeof(int)); count = malloc((max-min+1) * sizeof (int)); free(count); free(temp); for(i=min; i<=max; i++) count[i-min] = 0; 6/18

Quicksort Zerlegung des Feldes in zwei Teile Alles im ersten Teil ist kleiner als alles im Zweiten Rekursive Anwendung auf die beiden Teile Ein Teile und Herrsche Verfahren O(n*log n) für unsortierte Daten O(n²) bei sortierten Eingaben => Äußerst schnelles Erstsortierverfahren 6/19

Quicksort Code quicksort [] = [] quicksort (x:xs) = quicksort ys ++ [x] ++ quicksort zs where (ys,zs) = partition (<x) xs 6/20

Quicksort Code void quicksort(int* data, int len) { int l,r; if(len<2) return; for(l=0, r=len-1; l<r; ) { while(l<r && data[l]<=data[r]) r--; while(l<r && data[l]<=data[r]) l++; quicksort(data, l); quicksort(data+l+1, len-l-1); if(l<r) swap(data,l,r); if(l<r) swap(data,l,r); 6/21

Mergesort Zerlegen in gleichgroße Teile erzwingen Zusammenführen sortierter Teile einfach O(n*log n) in allen Fällen O(n) Platzbedarf für Umkopieren => Sehr schnelles Allzwecksortierverfahren 6/22

Mergesort Code mergesort [] = [] mergesort [x] = [x] mergesort xs = merge (mergesort ys) (mergesort zs) where (ys,zs) = splitat (length xs `div` 2) xs merge [] ys = ys merge xs [] = xs merge xs@(x:xs') ys@(y:ys') x <= y = x : merge xs' ys otherwise = y : merge xs ys' 6/23

Mergesort Code void mergesort(int* data, int len) { int len2, i, l, r, *temp; if(len < 2) return; len2 = len/2; mergesort(data, len2); mergesort(data+len2, len-len2); temp = malloc(len * sizeof(int)); for(i=0; i<len2; i++) temp[i] = data[i]; for(; i<len; i++) temp[i] = data[(len-1) (i-len2)]; /* Maximum steht in der Mitte */ for(i=0, l=0, r=len-1; i<len; i++) data[i] = temp[ temp[l] < temp[r]? l++ : r--]; free(temp); 6/24

Radix Exchange Sort Sortierung der Schlüssel nach fester Stelligkeit Höchstwertige Stellen zuerst (wie Quicksort) Die entstehenden Bereiche anhand der nächsten Stelle rekursiv sortieren Sortierung nach Bits ergibt Binärbaum O(n*log n) durchschnittlich O(n*bits) im schlimmsten Fall => Ähnlich Quicksort, verschiedene Schlüssel 6/25

Radix Exchange Sort Code void radixexchangesort1(int* data, int len, int radix, int mask) { int l,r,testbit = 1<<radix; if(len<2) return; /* Partitionierung anhand des vorgegeben Bits durchführen */ for(l=0, r=len-1; l<r; ) { while(l<r && (mask ^ data[r]) & testbit) r--; while(l<r && (mask ^ ~data[l]) & testbit) l++; if(l<r) swap(data,l,r); 6/26

Radix Exchange Sort Code if(radix>0) { /* Rekursiv weiter sortieren */ if((mask ^ data[l]) & testbit) { /* Trennstelle zuornden */ radixexchangesort1(data, l, radix-1, 0); radixexchangesort1(data+l, len-l, radix-1, 0); else { radixexchangesort1(data, l+1, radix-1, 0); radixexchangesort1(data+l+1, len-l-1, radix-1, 0); 6/27

Radix Exchange Sort Code void radixexchangesort(int* data, int len) { int radix = 8*sizeof(int)-1; /* höchstwertiges Bit */ /* Höchstwertiges Bit negativer Zahlen == 1 Deswegen im ersten Aufruf Bits invertieren */ radixexchangesort1(data, len, radix, ~0); 6/28

Straight Radix Sort Sortierung der Schlüssel nach fester Stelligkeit Niederwertigstewertige Stellen zuerst Stabilität des Sortierens notwendig Distribution Counting pro Stelle (fixer Speicher) bits/m Durchläufe bei O(2 m ) Speicher O(n) bei geschickter Wahl der Basis => Praktisch linear für kleine Schlüssel 6/29

Straight Radix Sort Code void straightradixsort1(int* data, int len, int radix, int mask) { int i,count[2] = {0, *temp = malloc(sizeof(int)*len); /* Klassisches Distribution Counting */ for(i=0; i<len; i++) count[((mask ^ (temp[i] = data[i]))>>radix) & 1]++; count[1] += count[0]; for(i=len; i-->0;) data[--count[((mask ^ temp[i])>>radix) & 1]] = temp[i]; free(temp); 6/30

void straightradixsort(int* data, int len) { int i; /* von niedrigen Bits zu höherwertigen */ for(i=0; i<sizeof(int)*8-1; i++) straightradixsort1(data, len, i, 0); /* höchstwertiges Bit invertiert behandeln */ straightradixsort1(data, len, i, ~0); 6/31

Prioritätswarteschlangen Teilsortierte Datenstruktur, die schnell: Erstellen der Struktur aus einem Feld Einfügen eines neues Elements Entfernen des wichtigsten Elements Ersetzen des wichtigsten Elements mit einem Neuen Ändern der Priorität eines beliebigen Elements Löschen eines beliebigen Elements Zusammenfügen zweier Heaps 6/32

Heap 8 7 3 6 5 1 [_,8,7,3,6,5,1,_,_,_,...] 0 1 2 3 4 5 6 7 8 9... Levelorder Zuordnung zwischen Baum und Feld i/2 -> Elternknoten 2*i und 2*i+1 -> Kindknoten Heapbedingung: Elt größer als Kindknoten Teilsortiert, deswegen Freiraum für Schnelligkeit 6/33

Heap Code struct Heap { insert(struct Heap* h, int neu) { int* feld; int n; /* Füllstand */ upheap(struct Heap* h, int i) { while(i>1 && h->feld[i] < h->feld[i/2]) { h->n++; h->feld[h->n] = neu; upheap(h, n); swap(h->feld, i, i/2); i /= 2; 6/34

Heap Code downheap(struct Heap* h, int i) { int j; /* größter Kindknoten */ while(j= 2*i; j <= h->n; i=j, j*=2;) { if(j < h->n && h->feld[j] < h->feld[j+1]) j++; /* größter Knoten ist rechts, nicht links */ if(h->feld[i] >= h->feld[j]) break; /* Abbruch, da nur kleinere Kindsknoten */ swap(h->feld, i, j); i = j; 6/35

Heap Code int remove(struct Heap* h) { int result = h->feld[1]; swap(h->feld, 1, h->n--); downheap(h, 1); return result; int replace(struct Heap* h, int v) { h->feld[0] = v; downheap(h, 0); return h->feld[0] ; heapsort(int* data, int len) { struct Heap h = {data-1, len; int i; for(i = len/2; i > 0; i--) { downheap(h, i); while(h.n > 0) { remove(h); 6/36

Heap Sort Anwendung einer Prioritätswarteschlange Trickreiche Inplace Anordnung Erweiterbar für externe Sortierverfahren Abbruch nach einigen Werten billig möglich O(n) für den Aufbau des Heaps O(n*log n) für die Sortierung => Schnelles (Teil)Sortierverfahren 6/37