Die Präsentation wird geladen. Bitte warten

Die Präsentation wird geladen. Bitte warten

InsertionSort Einfügen eines Elements an der richtigen Stelle eines bereits sortierten Arrays. Verschiebungen von Elementen statt Vertauschungen Element.

Ähnliche Präsentationen


Präsentation zum Thema: "InsertionSort Einfügen eines Elements an der richtigen Stelle eines bereits sortierten Arrays. Verschiebungen von Elementen statt Vertauschungen Element."—  Präsentation transkript:

1 InsertionSort Einfügen eines Elements an der richtigen Stelle eines bereits sortierten Arrays. Verschiebungen von Elementen statt Vertauschungen Element x = A[k] wird aus dem Array herausgenommen. So entsteht eine Lücke: DigInf 05/06

2 InsertionSort Einfügen eines Elements an der richtigen Stelle eines bereits sortierten Arrays. Verschiebungen von Elementen statt Vertauschungen Invariante für die äußere Schleife: A[0, ..., k-1] ist sortiert Algorithmus: Ausgehend von Position k führen wir ein BubbleDown durch Damit ist InsertionSort eine Variante von BubbleSort DigInf 05/06

3 InsertionSort Folgendes Programm arbeitet ohne Swap. Die Invariante
„Das Array A bleibt eine Permutation des ursprünglichen Arrays.“ muss wieder gesondert geprüft werden. static void InsertionSort(char[] A) { int Hi = A.length – 1; for (int k = 1; k <= Hi; k++) if (A[k] < A[k-1]) { char x = A[k]; int i; for (i = k; ((i > 0) && (A[i–1] > x)); i--) A[i] = A[i–1]; A[i] = x; } Verkürzte Auswertung DigInf 05/06

4 InsertionSort - Laufzeitverhalten
Aufwand für InsertionSort wie für SelectionSort mit folgenden Unterschieden: Average case: Für das Aufspüren der endgültigen Position des Elements A[k] werden k / 2 Vergleiche benötigt, bei SelectionSort müssen zum Auffinden von minPos alle noch ungeordneten Elemente untersucht werden. Worst case: SelectionSort benötigt maximal N Swaps. Bei InsertionSort werden schlimmstenfalls N2 / 2 Elemente bewegt. Bei InsertionSort ist eine kürzere Laufzeit zu erwarten, wenn die Elemente kurz sind (geringer Aufwand für zusätzliche Swaps) oder wenn die Elemente gut vorsortiert sind. DigInf 05/06

5 Laufzeitvergleiche Zeit in Sekunden, zufällig sortierte Elemente
bereits sortierte Elemente DigInf 05/06

6 ShellSort Variante von InsertionSort
Name geht auf den Erfinder Donald Shell zurück Idee: der letzte Durchgang ist ein klassisches InsertionSort alle Durchgänge vorher sorgen für eine gute Vorsortierung Laufzeit: O(N1,5), experimentell sogar O(N1,25) Mit h = 1 ergibt sich das klassische InsertionSort static void InsertionSort(char[] A, int h) { int Hi = A.length – 1; for (int k = h; k <= Hi; k++) if (A[k] < A[k-h]) { char x = A[k]; int i; for (i = k; ((i > (h-1)) && (A[i–h] > x)); i = i-h) A[i] = A[i–h]; A[i] = x; } DigInf 05/06

7 ShellSort InsertionSort wird mit einer bestimmten absteigenden Folge von Werten für h aufgerufen. Eine bewährte Folge ist ..., 121, 40, 13, 4, 1 mit dem Bildungsgesetz: h0 = 1, hn+1 = 3 * hn + 1 Der letzte Aufruf mit 1 garantiert, dass korrekt sortiert ist. static void ShellSort(char[] A) { int Hi = A.length – 1; int hmax, h; for (hmax = 1; hmax < Hi; hmax = 3*hmax+1) { } for (h = hmax/3; h > 0; h = h/3) InsertionSort(A, h); } DigInf 05/06

8 Schnelle Sortieralgorithmen
Es gibt Sortieralgorithmen mit einer Laufzeit von N * log N Dazu gehören HeapSort, QuickSort, MergeSort (dazu später mehr) Schneller geht’s im allgemeinen Fall nicht! DigInf 05/06

9 QuickSort QuickSort ist ein „Divide and Conquer“-Algorithmus, das bedeutet, er hat die folgende Struktur: Zerlege das Problem P in Teilprobleme P1, ..., Pn Finde die Lösungen L1, ..., Ln der Teilprobleme Setze die Lösung L von P aus den Lösungen der Teilprobleme zusammen Divide and Conquer-Algorithmen sind oft rekursiv Für n = 2: lösungsTyp dac(problemTyp P) { if (istTrivial(P)) return trivialLösung; else return combine(dac(Teil1(P)), dac(Teil2(P))); } DigInf 05/06

10 QuickSort 1960 erfunden von C.A.R. Hoare
Suche nach besserem Algorithmus zeigte sich als erfolgreicher als Tricksen an existierenden Algorithmen Array A, w = A[k] irgendwie auswählen, w heißt Pivot-Element Partitioniere übrige Elemente von A in kleinere Arrays A1 und A2, so dass alle Elemente von A1 sind ≤ w, alle Elemente von A2 sind ≥ w. Bringt man nun w zwischen A1 und A2, so gilt für die neue Anordnung A1 w A2 :  x  A1,  y  A2 : x ≤ w ≤ y Nun sortiert man A1 und A2 mit QuickSort und erhält sortierte Variante des ursprünglichen Arrays A A w A1 A2 w A1 A2 w QuickSort QuickSort B1 B2 w DigInf 05/06

11 QuickSort QuickSort funktioniert besonders gut, wenn es gelingt das Pivot-Element so zu wählen, dass A1 und A2 gleich groß sind. QuickSort wird mit drei Argumenten aufgerufen: Array A Linke Grenze li Rechte Grenze re Für die Wahl des Pivot-Elements gibt es eine Reihe von Heuristiken: w = A[li] w = A[re] w = A[mid] mit mid = (li + re) / 2 Für alle Heuristiken gibt es Beispielsituationen, in denen sie gut oder schlecht funktionieren. Im Beispiel „S O R T I E R B E I S P I E L“ ergibt sich mit w = A[mid] („B“) die schlechtestmögliche Partionierung, A1 bleibt leer. Verbesserte Heuristik: den mittleren Wert von A[li], A[re], A[mid] DigInf 05/06

12 QuickSort – Partitionierung per swap
Setze i = li und j = re. Solange li < i < j < re gilt, führe folgende Schritte durch: inkrementiere i solange A[ i ] < w , dekrementiere j solange A[ j ] > w, vertausche A[ i ] mit A[ j ], inkrementiere i und dekrementiere j. DigInf 05/06

13 QuickSort – Beweis der Korrektheit
Induktion über die Anzahl n der Elemente eines beliebig zu ordnenden Array-Abschnitts A[li .. re]. Vorausgesetzt sei die Korrektheit des Partionierungsalgorithmus. Falls n = 1 d.h. li = re ist A sortiert und QuickSort ändert nichts. Induktionsannahme: QuickSort sortiert maximal k-elementige Abschnitte korrekt. Wir betrachten ein A mit n = k+1 Elementen. Im ersten Schritt entsteht eine Partition A1 w A2, so dass gilt: u  w  v für alle u aus A1 und alle v aus A2 A1 w A2 ist eine Permutation von A QuickSort angewendet auf die höchstens k-elementigen A1 und A2 liefert A´1 und A´2. Die sind geordnete Permutation von A1 und A2. Es folgt u  w  v für alle u aus A´1 und alle v aus A´2 Und damit: A´1 w A´2 ist geordnete Permutation von A1 w A2, also auch von A. DigInf 05/06

14 QuickSort – Komplexität
Günstigster Fall: Aufrufhierarchie hat log2(N) Ebenen. Jede Ebene enthält alle Elemente des Arrays genau einmal, so dass für die Partionierung einer Ebene die Zeit c * N benötigt wird. Gesamtaufwand ist dann c * N * log2(N) Ungünstigster Fall: Baum wird zur Kette von N Elementen. Aufwand ist dann proportional zu N2. DigInf 05/06

15 QuickSort – Implementierung
static void QuickSort(char[] A) { int Hi = A.length – 1; RekQuickSort(A, 0, Hi); } static void RekQuickSort(char[] A, int Lo, int Hi) { int li = Lo; int re = Hi; int mid = (li + re) / 2; if (A[li] > A[mid]) Swap(A, li, mid); if (A[mid] > A[re]) Swap(A, mid, re); if ((re – li) > 2) { char w = A[mid]; do { while (A[li] < w) li++; while (w < A[re]) re--; if (li <= re) { Swap(A, li, re); li++; re--; } } while (li <= re); if (Lo < re) RekQuickSort(A, Lo, re); if (li < Hi) RekQuickSort(A, li, Hi); DigInf 05/06

16 MergeSort MergeSort ist ein „Divide and Conquer“-Algorithmus.
Aufteilung in zwei Hälften, die separat sortiert und dann zusammengemischt werden. Zusammenmischen bedeutet, dass die kleinsten Elemente jeweils verglichen und gemischt werden. DigInf 05/06

17 MergeSort – Implementierung
static void MSort(char[] A, int Lo, int Hi) { if (Lo < Hi) { int Mid = (Lo + Hi + 1) / 2; MSort(A, Lo, Mid – 1); MSort(A, Mid, Hi); Merge(A, Lo, Mid, Hi); } Hilfsarray Temp nimmt die zusammengemischten Teil-Arrays auf. Temp wird zum Schluss wieder in A[Lo...Hi] zurückkopiert. static void Merge(char[] A, int Lo, int Mid, int Hi) { char Temp[] = new char[Hi – Lo + 1]; for (int i = 0, j = Lo, k = Mid; i < Temp.length; i++) { if ((k > Hi) || (j < Mid) && (A[j] < A[k])) { Temp[i] = A[j]; j++; } else { Temp[i] = A[k]; k++; } for (int i = 0; i < Temp.length; i++) A[Lo + i] = Temp[i]; DigInf 05/06

18 MergeSort – Beispiel DigInf 05/06

19 DistributionSort Bisherige Sortieralgorithmen basierten auf Vergleich und Vertauschen zweier Elemente. Diese Algorithmen (und alle anderen auf Vergleichen basierende) haben mindestens den Aufwand N log (N). Distribution kommt ohne Vergleiche aus. Voraussetzung: Daten haben Sortierschlüssel mit festem Format (z.B. Ziffernfolge) Grundidee: Die zu sortierenden Daten werden anhand einer Ziffernposition auf Fächer verteilt und wieder zusammen getragen. Verteilung erfolgt zunächst anhand der letzten Position, trägt zusammen und setzt dann mit Verteilung gemäß zweitletzter Ziffernposition fort. DigInf 05/06

20 DistributionSort – Beispiel
Briefe werden nach Postleitzahlen sortiert. Verteilen aller Briefe auf Fächer gemäß der letzten Ziffer der PLZ Zusammentragen unter Beibehaltung der Ordnung Verteilung aller Briefe gemäß der vorletzten Ziffer Fortsetzen bis zur ersten PLZ-Ziffer Zusammentragen führt zu vollständiger Sortierung DigInf 05/06

21 DistributionSort – Beispiel
DigInf 05/06

22 DistributionSort – Beispiel
DigInf 05/06

23 DistributionSort – Korrektheitsbeweis durch Induktion
Induktion über die Länge des Sortierschlüssels DigInf 05/06

24 DistributionSort – Laufzeit und Einschränkungen
DistributionSort arbeitet mit beschränktem Schlüssel und kann deshalb auch nur für eine feste Zahl von zu sortierenden Daten eingesetzt werden. Von daher ist kein „fairer“ Vergleich bei asymptotischer Abschätzung möglich. Innerhalb der maximalen Sortiermenge ist DistributionSort laufzeit-linear. Konkret: Jedes Einordnen ist linear, also c*N und das ist k-mal (k = Schlüssellänge) zu wiederholen, also ist der Aufwand k*c*N, d.h. O(N). DigInf 05/06

25 DistributionSort – Laufzeit und Einschränkungen
Zwei Probleme: Ordnung der Schlüsselwerte spiegelt nicht immer die Ordnung auf den Daten wider (z.B. Kodierung von Zeichenketten) In jedem Sortierfach muss Platz für alle Datensätze sein. Bei 10 Sortierfächern braucht man entsprechend 10 mal Platz für das gesamte Array. DigInf 05/06

26 DistributionSort – Implementierung
static void DistributionSort(Element[] A, int m) { // m Schlüssellänge for (int k = m; k > 0; k--) { // für jede Schlüsselposition int Count[] = new int[d]; // Count initialisieren for (int z = 0; z < d; z++) // Zeichenmenge für Schlüssel Count[z] = 0; // ist 0..(d-1) for (int i = 0; i < A.length; i++) // Bedarf für die Fachgröße Count[ Key(k, A[i]) ]++; // bestimmen for (int z = 0; z < d; z++) // Aufsummieren Count[z] += Count[z-1]; for (int z = d-1; z > 0; z--) // Beginn d. Fächer bestimmen Count[z] = Count[z-1]; // Fach für Zeichen z beginnt Count[0] = 0; // jetzt an Pos. Count[z] Element B[] = new Element[A.length]; for (int i = 0; i < A.length; i++) { // Einordnen, int z = Key(k, A[i]); // dabei Fachgrenze B[Count[z]++] = A[i]; // anpassen } System.arraycopy(B, 0, A, 0, A.length); DigInf 05/06

27 Laufzeit der schnellen Sortieralgorithmen
Zusätzlich: java.util.Arrays.sort(int[] a) (Quicksort ähnlich) Grundlage: Pentium 4 PC Zufällig sortierte Daten, N = Anzahl der zu sortierenden Daten DigInf 05/06

28 Laufzeit der schnellen Sortieralgorithmen
Zusätzlich: java.util.Arrays.sort(int[] a) (Quicksort ähnlich) Grundlage: Pentium 4 PC Vollständig vorsortierte Daten, N = Anzahl der zu sortierenden Daten DigInf 05/06

29 Regeln zur Wahl des Sortieralgorithmus
Bei geringen Datenmengen (kleiner als 20000) nimmt man einen einfachen Algorithmus (InsertionSort, SelectionSort, BubbleSort) Für einen gut vorsortierten Datenbestand bieten sich InsertionSort und BubbleSort an. Hat man zufällig verteilte Daten und muss man oft sortieren, dann bietet sich eine Anpassung von DistributionSort an. Ist das Risiko einer ungünstigen Verteilung (und damit das Worst Case Verhalten) ertragbar, dann QuickSort. Ansonsten ShellSort, MergeSort, HeapSort. DigInf 05/06

30 Online-Feedback Bewertung von bis Sonntag unter nur mit Feedback-TAN
Vorlesung Übungen Begleitmaterial bis Sonntag unter nur mit Feedback-TAN gültig für eine Stimme Austeilung in Vorlesung Ergebnisse ab 6.2. im Netz DigInf 05/06


Herunterladen ppt "InsertionSort Einfügen eines Elements an der richtigen Stelle eines bereits sortierten Arrays. Verschiebungen von Elementen statt Vertauschungen Element."

Ähnliche Präsentationen


Google-Anzeigen