Die Präsentation wird geladen. Bitte warten

Die Präsentation wird geladen. Bitte warten

1 DigInf 05/06 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: "1 DigInf 05/06 Einfügen eines Elements an der richtigen Stelle eines bereits sortierten Arrays. Verschiebungen von Elementen statt Vertauschungen Element."—  Präsentation transkript:

1 1 DigInf 05/06 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: InsertionSort

2 2 DigInf 05/06 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 InsertionSort

3 3 DigInf 05/06 Folgendes Programm arbeitet ohne Swap. Die Invariante „Das Array A bleibt eine Permutation des ursprünglichen Arrays.“ muss wieder gesondert geprüft werden. Verkürzte Auswertung 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; } InsertionSort

4 4 DigInf 05/06 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 N 2 / 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. InsertionSort - Laufzeitverhalten

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

6 6 DigInf 05/06 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(N 1,5 ), experimentell sogar O(N 1,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; } ShellSort

7 7 DigInf 05/06 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: h 0 = 1, h n+1 = 3 * h n + 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); } ShellSort

8 8 DigInf 05/06 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! Schnelle Sortieralgorithmen

9 9 DigInf 05/06 QuickSort ist ein „Divide and Conquer“-Algorithmus, das bedeutet, er hat die folgende Struktur: Zerlege das Problem P in Teilprobleme P 1,..., P n Finde die Lösungen L 1,..., L n 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))); } QuickSort

10 10 DigInf 05/ 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 A 1 und A 2, so dass alle Elemente von A 1 sind ≤ w, alle Elemente von A 2 sind ≥ w. Bringt man nun w zwischen A 1 und A 2, so gilt für die neue Anordnung A 1 w A 2 :  x  A 1,  y  A 2 : x ≤ w ≤ y Nun sortiert man A 1 und A 2 mit QuickSort und erhält sortierte Variante des ursprünglichen Arrays A A w A1A1 A2A2 w ≤ ≤ A1A1 A2A2 w ≤ ≤ B1B1 B2B2 w ≤ ≤ QuickSort

11 11 DigInf 05/06 QuickSort funktioniert besonders gut, wenn es gelingt das Pivot-Element so zu wählen, dass A 1 und A 2 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, A 1 bleibt leer. Verbesserte Heuristik: den mittleren Wert von A[li], A[re], A[mid] QuickSort

12 12 DigInf 05/06 Partitionierung: 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. QuickSort – Partitionierung per swap

13 13 DigInf 05/06 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 A 1 w A 2, so dass gilt: u  w  v für alle u aus A 1 und alle v aus A 2 A 1 w A 2 ist eine Permutation von A QuickSort angewendet auf die höchstens k-elementigen A 1 und A 2 liefert A´ 1 und A´ 2. Die sind geordnete Permutation von A 1 und A 2. 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 A 1 w A 2, also auch von A. QuickSort – Beweis der Korrektheit

14 14 DigInf 05/06 Günstigster Fall: Aufrufhierarchie hat log 2 (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 * log 2 (N) Ungünstigster Fall: Baum wird zur Kette von N Elementen. Aufwand ist dann proportional zu N 2. QuickSort – Komplexität

15 15 DigInf 05/06 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 (A[li] > A[mid]) Swap(A, li, mid); 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); } QuickSort – Implementierung

16 16 DigInf 05/06 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. MergeSort

17 17 DigInf 05/06 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]; } MergeSort – Implementierung

18 18 DigInf 05/06 MergeSort – Beispiel

19 19 DigInf 05/06 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. DistributionSort

20 20 DigInf 05/06 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 Zusammentragen unter Beibehaltung der Ordnung Fortsetzen bis zur ersten PLZ-Ziffer Zusammentragen führt zu vollständiger Sortierung DistributionSort – Beispiel

21 21 DigInf 05/06 DistributionSort – Beispiel

22 22 DigInf 05/06 DistributionSort – Beispiel

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

24 24 DigInf 05/06 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). DistributionSort – Laufzeit und Einschränkungen

25 25 DigInf 05/06 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. DistributionSort – Laufzeit und Einschränkungen

26 26 DigInf 05/06 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); } DistributionSort – Implementierung

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

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

29 29 DigInf 05/06 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. Regeln zur Wahl des Sortieralgorithmus

30 30 DigInf 05/06 Online-Feedback Bewertung von 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


Herunterladen ppt "1 DigInf 05/06 Einfügen eines Elements an der richtigen Stelle eines bereits sortierten Arrays. Verschiebungen von Elementen statt Vertauschungen Element."

Ähnliche Präsentationen


Google-Anzeigen